<?php

namespace App\V3\V3_2\Services;

use App\Services\CommonService;
use App\V3\V3_2\Models\LogInStorageModel;
use App\V3\V3_2\Models\LogOutPackageModel;
use App\V3\V3_2\Models\LogOutStorageModel;
use App\V3\V3_2\Models\LogPackageContentModel;
use App\V3\V3_2\Models\LogPackageModel;
use App\V3\V3_2\Models\MaterielClassModel;
use App\V3\V3_2\Models\MaterielModel;
use App\V3\V3_2\Models\MaterielProductContentModel;
use App\V3\V3_2\Models\MaterielsTypeModel;
use App\V3\V3_2\Models\MaterielTypeModel;
use App\V3\V3_2\Models\OverflowBreakageModel;
use App\V3\V3_2\Models\PackageContentModel;
use App\V3\V3_2\Models\PackageModel;
use App\V3\V3_2\Models\ProductOrderModel;
use App\V3\V3_2\Models\SalesReturnModel;
use App\V3\V3_2\Models\SellGoodsDetailBatchModel;
use App\V3\V3_2\Models\SellGoodsDetailModel;
use App\V3\V3_2\Models\SellMaterielPrepareOutLogModel;
use App\V3\V3_2\Models\SellModel;
use App\V3\V3_2\Models\SellPackageContentModel;
use App\V3\V3_2\Models\SellPackageDetailModel;
use App\V3\V3_2\Models\SerialNumberModel;
use App\V3\V3_2\Models\StorageBatchModel;
use App\V3\V3_2\Models\StorageManageModel;
use App\V3\V3_2\Models\StorageModel;
use App\V3\V3_2\Models\StorageShelfLocationModel;
use App\V3\V3_2\Models\StorageShelfModel;
use App\V3\V3_2\Models\CheckModel;
use App\V3\V3_2\Models\SellGoodsDetail;
use App\Services\MessageService;
use App\V3\V3_2\Models\TallyModel;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Redis;
use App\V3\V3_2\Models\SellGoodsListModel;
use App\V3\V3_2\Models\SellOutSerialNumbersModel;
use App\V3\V3_2\Models\PackageComponentWarehouseLogModel;
class StorageManageService
{
    static public function readGoodsIdInfo($data)
    {
        //查询是否是组件的id，如果是返回组件套餐id
        $info = MaterielTypeModel::where('id',  $data['goods_id'])

        -> where('delete_flag',0)
        -> first()->toArray();

        if(!empty($info['id'])){
            return $info;
        }else{
            return "";
        }
    }
    static public function checkMatierlInStorageOrNot($id, $mainId)
    {
        $info = StorageManageModel::where([
            'type_id' => $id,
            'main_id' => $mainId,
            'delete_flag' => 0
        ])->where('in_storage_num', '!=', 0)->first();

        if(!empty($info)) {
            return false;
        }
        else {
            return true;
        }
    }
    //删除库存信息
    static public function del($data)
    {
        $storageManageInfo = StorageManageModel::where('id', $data['id'])->first();

        if($storageManageInfo['in_storage_num'] != 0) {
            return ['code' => 1, 'msg' => '当商品库存数为0时才可删除，当前库存数为：'.$storageManageInfo['in_storage_num'], 'data' => ''];
        }

        StorageManageModel::where('id', $data['id'])
        ->update(['delete_flag' => 1]);

        return ['code' => 0, 'msg' => 'success', 'data' => ''];
    }

    //库存查看列表
    static public function list($parentId, $data)
    {
        $keyword = empty($data['keyword'])?'':$data['keyword'];
        $condition = [];
        if(!empty($data['materiel_class_id'])) {
            $condition['c.id'] = ['EQ' => $data['materiel_class_id']];
        }

        if(isset($data['is_product_materiel'])) {
            $condition['a.is_product_materiel'] = ['EQ' => $data['is_product_materiel']];
        }

        if(isset($data['is_product_storage'])) {
            $condition['e.is_product_storage'] = ['EQ' => $data['is_product_storage']];
        }

        $result = [];
        switch($data['order_type']) {
            case 0:
                $result = self::defaultOrder($parentId, $keyword, $condition, $data);
                break;
            case 1:
                $result = self::orderByInstorageNum($parentId, $keyword, $condition, $data);
                break;
            case 2:
                $result = self::orderByCharset($parentId, $keyword, $condition, $data);
                break;
        }

        return $result;
    }

    //首字母排序
    private static function orderByCharset($parentId, $keyword, $condition, $data)
    {
        $result = StorageManageModel::orderByCharset($parentId, $keyword, $condition, $data);

        foreach($result as &$value) {
            $materielTypeInfo = MaterielTypeModel::where('id', $value['type_id'])->first();
//                'b.materiel_name',
//                'b.type_name',
//                'b.materiel_no',
//                'b.materiel_img',
//                'b.is_product_materiel',
//                'b.remark',
//                'b.is_use_serial',
//                'b.materiel_unit',
            $value['materiel_name'] = $materielTypeInfo['materiel_name'];
            $value['type_name'] = $materielTypeInfo['type_name'];
            $value['materiel_no'] = $materielTypeInfo['materiel_no'];
            $value['materiel_img'] = $materielTypeInfo['materiel_img'];
            $value['is_product_materiel'] = $materielTypeInfo['is_product_materiel'];
            $value['remark'] = $materielTypeInfo['remark'];
            $value['is_use_serial'] = $materielTypeInfo['is_use_serial'];
            $value['materiel_unit'] = $materielTypeInfo['materiel_unit'];

            if($materielTypeInfo['is_product_materiel'] == 1) {
                $productList = MaterielProductContentModel::select(
                    'a.id',
                    'b.materiel_name',
                    'b.type_name',
                    'b.materiel_img',
                    'b.materiel_no',
                    'a.product_id',
                    'a.num',
                    'a.price',
                    'a.type_id',
                    'a.total_price'
                )
                    ->from('materiel_product_content as a')
                    ->leftJoin('materiel_type as b','b.id','=','a.type_id')
                    ->where('a.product_id',$value['type_id'])->get()->toArray();

                $value['product_content'] = $productList;
            }
            else {
                $value['product_content'] = [];
            }
        }

        return $result;
    }

    //库存数排序
    private static function orderByInstorageNum($parentId, $keyword, $condition, $data)
    {
        $result = StorageManageModel::list($parentId, $keyword, $condition, $data);

        $test1 = [];
        foreach($result as $vv1) {
            $test1[$vv1['type_id']][] = $vv1;

        }

        $arr1 = [];
        foreach($test1 as $vaa) {
            foreach($vaa as $vaaa) {
                $arr1[] = $vaaa;
            }
        }

        $keywordLength = strlen($keyword);
        $arr = [];

        foreach($arr1 as $key =>  $value) {
            if(substr($value['materiel_name'], 0, $keywordLength) == $keyword) {
                $arr[$key] = $value;
                unset($arr1[$key]);
            }
        }

        foreach($arr1 as $k => $val) {
            if(preg_match('/'.$data['keyword'].'/', $val['materiel_name'])) {
                $arr[$k] = $val;
                unset($arr1[$k]);
            }
        }

        foreach($arr1 as $k1 => $v1) {
            $arr[$k1] = $v1;
        }

        if($data['order_by'] == 'desc') {
            usort($arr, function($a, $b) {
                if($a['in_storage_num'] == $b['in_storage_num']) {
                    return 0;
                }
                return ($a['in_storage_num'] > $b['in_storage_num'])?-1:1;
            });
        }
        else {
            usort($arr, function($a, $b) {
                if($a['in_storage_num'] == $b['in_storage_num']) {
                    return 0;
                }
                return ($a['in_storage_num'] > $b['in_storage_num'])?1:-1;
            });
        }

        if(!empty($arr)) {
            foreach ($arr as $key => $val) {
                if($val['is_product_materiel'] && $val['in_storage_num'] == 0) {
                    unset($arr[$key]);
                }
                else {
                    if($val['is_product_materiel'] == 1) {
                        $productList = MaterielProductContentModel::select(
                            'a.id',
                            'b.materiel_name',
                            'b.type_name',
                            'b.materiel_img',
                            'b.materiel_no',
                            'a.product_id',
                            'a.num',
                            'a.price',
                            'a.type_id',
                            'a.total_price'
                        )
                            ->from('materiel_product_content as a')
                            ->leftJoin('materiel_type as b','b.id','=','a.type_id')
                            ->where('a.product_id',$val['type_id'])->get()->toArray();

                        $arr[$key]['product_content'] = $productList;
                    }
                    else {
                        $arr[$key]['product_content'] = [];
                    }
                }
            }
        }

        $currentPage = $data['currentPage'];
        $result = array_slice(array_values($arr), --$data['currentPage'] * $data['pageSize'], $data['pageSize']);

        return [
            'total' => count($arr),
            'current_page' => $data['currentPage'],
            'next_page_url' => count($result) < $data['pageSize']?null:config('app.url')."storage_manage_list?=".($data['currentPage']+1),
            'prev_page_url' => $data['currentPage']==1?null:config('app.url')."storage_manage_list?=".($currentPage-1),
            "path" => config('app.url')."storage_manage_list",
            "to" => $data['currentPage'] * $data['pageSize'],
            'data' => $result,
            "per_page" => $data['pageSize']
        ];
    }

    //默认排序方式-综合排序
    private static function defaultOrder($parentId, $keyword,$condition,$data)
    {
        $result = StorageManageModel::list($parentId, $keyword, $condition, $data);

        $test1 = [];
        foreach($result as $vv1) {
            $test1[$vv1['type_id']][] = $vv1;

        }

        $arr1 = [];
        foreach($test1 as $vaa) {
            foreach($vaa as $vaaa) {
                $arr1[] = $vaaa;
            }
        }

        $keywordLength = strlen($keyword);
        $arr = [];

        foreach($arr1 as $key =>  $value) {
            if(substr($value['materiel_name'], 0, $keywordLength) == $keyword) {
                $arr[$key] = $value;
                unset($arr1[$key]);
            }
        }

        foreach($arr1 as $k => $val) {
            if(preg_match('/'.$data['keyword'].'/', $val['materiel_name'])) {
                $arr[$k] = $val;
                unset($arr1[$k]);
            }
        }

        foreach($arr1 as $k1 => $v1) {
            $arr[$k1] = $v1;
        }

        usort($arr, function($a, $b) {
            if(!$a['sort_flag']) {
                if($a['in_storage_num'] == $b['in_storage_num']) {
                    return 0;
                }
                return ($a['in_storage_num'] > $b['in_storage_num'])?-1:1;
            }
        });
        if(!empty($arr)) {
            foreach ($arr as $key => $val) {
                if($val['is_product_materiel'] && $val['in_storage_num'] == 0) {
                    unset($arr[$key]);
                }
                else {
                    if($val['is_product_materiel'] == 1) {
                        $productList = MaterielProductContentModel::select(
                            'a.id',
                            'b.materiel_name',
                            'b.type_name',
                            'b.materiel_img',
                            'b.materiel_no',
                            'a.product_id',
                            'a.num',
                            'a.price',
                            'a.type_id',
                            'a.total_price'
                        )
                            ->from('materiel_product_content as a')
                            ->leftJoin('materiel_type as b','b.id','=','a.type_id')
                            ->where('a.product_id',$val['type_id'])->get()->toArray();

                        $arr[$key]['product_content'] = $productList;
                    }
                    else {
                        $arr[$key]['product_content'] = [];
                    }
                }
            }
        }

        $currentPage = $data['currentPage'];
        $result = array_slice(array_values($arr), --$data['currentPage'] * $data['pageSize'], $data['pageSize']);

        return [
            'total' => count($arr),
            'current_page' => $data['currentPage'],
            'next_page_url' => count($result) < $data['pageSize']?null:config('app.url')."storage_manage_list?=".($data['currentPage']+1),
            'prev_page_url' => $data['currentPage']==1?null:config('app.url')."storage_manage_list?=".($currentPage-1),
            "path" => config('app.url')."storage_manage_list",
            "to" => $data['currentPage'] * $data['pageSize'],
            'data' => $result,
            "per_page" => $data['pageSize']
        ];
    }

    /**
     * 审批出库
     * @param $userId
     * @param $mainId
     * @param $data
     * @param $sellId
     * AUTHOR  : Sun Wu
     * DateTime: 2022/7/6 17:13
     * @return array
     */
    static public function checkOutStorage($isUseShelf, $userId, $mainId, $data, $sellId = 0, $overflowBreakagePackageInfo)
    {
        if(!empty($data['content'])) {
            self::materielOutStorage($isUseShelf, $userId, $mainId, $data, $sellId);
        }

        if(!empty($overflowBreakagePackageInfo)) {
            self::packageOutStorage($isUseShelf, $userId, $mainId, $data, $overflowBreakagePackageInfo);
        }

        return ['code' => 0, 'msg' => '', 'data' => ''];
    }

    static private function packageOutStorage($isUseShelf, $userId, $mainId, $data, $package)
    {
        //出库信息
        $outStorageNumInfo = [];
        $logPackageInfo = [];

        foreach($package as $key => $value) {


            foreach($value['package_content'] as $val) {
                if($val['in_storage_num'] < $val['total_num']) {
                    throw new Exception('库存剩余数量不足');
                }

                if($val['virtual_storage_num'] < $val['total_num']) {
                    throw new Exception('库存可预出库剩余数量不足');
                }

                if(!$isUseShelf || $value['shelf_id'] == 0) {
                    $shelfInfo = StorageShelfModel::where('storage_id', $value['warehouse'])
                        ->where('shelf_type', 1)->first();

                    $shelfLocationInfo = StorageShelfLocationModel::where('shelf_id', $shelfInfo['id'])
                        ->where('location_type', 1)->first();
                }
                else {
                    $shelfInfo = StorageShelfModel::where('storage_id', $value['warehouse'])->where('id', $value['shelf_id'])->first();

                    if(empty($shelfInfo)) {
                        throw new Exception('无效货架，请重试');
                    }

                    $shelfLocationInfo = StorageShelfLocationModel::where('shelf_id', $value['shelf_id'])
                        ->where('shelf_location_id', $value['shelf_location_id'])->first();

                    if(empty($shelfLocationInfo)) {
                        throw new Exception('无效库位，请重试');
                    }
                }

                //序列号
                if($isUseSerial && empty($value['serial_number'])) {
                    throw new Exception('请填写序列号');
                }
                else if($isUseSerial && !empty($value['serial_number'])) {
                    $serialNumberInfo = array_filter(explode(',', $value['serial_number']), function($v) { return $v !== ''; });

                    $checkSerialNumber = SerialNumberModel::where('storage_manage_id', $value['id'])->whereIn('serial_no', $serialNumberInfo)->get()->toArray();

                    $arr1 = [];
                    foreach($checkSerialNumber as $vv1) {
                        if($vv1['status']) {
                            throw new Exception('序列号：'.$vv1['serial_no'].'已使用');
                        }

                        $arr1[] = [
                            'id' => $vv1['id'],
                            'status' => 1
                        ];
                    }

                    batch()->update(new SerialNumberModel, $arr1, 'id');
                }

                LogPackageContentModel::insert([
                    'log_package_id' => $logId,
                    'package_id' => $value['package_id'],
                    'storage_id' => $val['storage_id'],
                    'storage_name' => $val['storage_name'],
                    'storage_address' => $val['storage_address'],
                    'materiel_class_id' => $val['materiel_class_id'],
                    'materiel_class_name' => $val['materiel_class_name'],
                    'materiel_class_no' => $val['materiel_class_no'],
                    'materiel_type_id' => $val['type_id'],
                    'materiel_name' => $val['materiel_name'],
                    'type_name' => $val['type_name'],
                    'materiel_no' => $val['materiel_no'],
                    'operate_num' => $val['total_num'],
                    'shelf_id' => $shelfInfo['shelf_id'],
                    'location_id' => $shelfLocationInfo['location_id'],
                    'out_storage_manage_id' => $val['storage_manage_id'],
                    'last_storage_num' => $val['in_storage_num'],
                    'next_storage_num' => $val['in_storage_num'] - $val['total_num'],
                    'all_id_type' => 2,
                    'all_id' => $data['all_id'],
                    'user_id' => $userId,
                    'main_id' => $mainId,
                    'created_at' => time()
                ]);

                StorageManageModel::where('id', $val['storage_manage_id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num - '.$val['total_num']),
                        'virtual_storage_num' => DB::raw('virtual_storage_num - '.$val['total_num'])
                    ]);

                MessageService::sendAlertSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['total_num'],
                    $val['alert_num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $val['id'],
                    $val['storage_name'],
                    $val['total_num']
                );

                MessageService::sendShortSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['total_num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $val['storage_name'],
                    $val['id']
                );

                MessageService::sendOutSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['total_num'],
                    $val['storage_name'],
                    $val['total_num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $val['id'],
                   $val['alert_num'],
                );
            }
        }
        return true;
    }

    static private function materielOutStorage($isUseShelf, $userId, $mainId, $data, $sellId)
    {
        $logOutstorageData = [];//出库操作记录数据
        $outstorageNumsData = [];//库存数据信息-更新库存
        $returnData = [];//返回数据

        foreach($data['content'] as $key => $value) {
            //物料商品信息
            $materielTypeInfo = MaterielsTypeModel::select(
                'a.id',
                'materiel_name',
                'type_name',
                'materiel_no',
                'b.id as materiel_class_id',
                'b.class_name',
                'b.class_no',
                'a.is_use_serial'
            )
                ->from('materiel_type as a')
                ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                ->where([
                    'materiel_name' => $value['name'],
                    'type_name' => $value['type_name'],
                    'a.main_id' => $mainId,
                    'a.delete_flag' => 0,
                ])
                ->first();

            if(empty($materielTypeInfo)) {
                throw new Exception('物料`'.$value['name'].'-'.$value['type_name'].'`不存在');
            }

            //仓库信息
            $storageInfo = StorageModel::where([
                'storage_name' => $value['warehouse'],
                'id' => $value['warehouse_id'],
                'main_id' => $mainId,
                'delete_flag' => 0,
            ])->first();

            if(empty($storageInfo)) {
                throw new Exception('仓库`'.$value['warehouse'].'`不存在');
            }

            if(!$isUseShelf || $value['shelf_id'] == 0) {
                $shelfInfo = StorageShelfModel::where('storage_id', $value['warehouse'])
                    ->where('shelf_type', 1)->first();

                $shelfLocationInfo = StorageShelfLocationModel::where('shelf_id', $shelfInfo['id'])
                    ->where('location_type', 1)->first();
            }
            else {
                $shelfInfo = StorageShelfModel::where('storage_id', $value['warehouse'])->where('id', $value['shelf_id'])->first();

                if(empty($shelfInfo)) {
                    return ['code' => 1, 'msg' => '无效货架，请重试', 'data' => ''];
                }

                $shelfLocationInfo = StorageShelfLocationModel::where('shelf_id', $value['shelf_id'])
                    ->where('shelf_location_id', $value['shelf_location_id'])->first();

                if(empty($shelfLocationInfo)) {
                    return ['code' => 1, 'msg' => '无效库位，请重试', 'data' => ''];
                }
            }

            //物料当前库存信息
            $storageManageInfo = StorageManageModel::where([
                'type_id' => $materielTypeInfo['id'],
                'storage_id' => $storageInfo['id'],
                'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                'main_id' => $mainId,
                'delete_flag' => 0
            ])->first();

            //检查库存中是否存在该物料
            if(empty($storageManageInfo)) {
                throw new Exception('库存中物料`'.$value['name'].'-'.$value['type_name'].'`不存在');
            }

            if($storageManageInfo['in_storage_num'] < $value['num']) {
                throw new Exception('当前库存剩余数量不足，无法完成出库');
            }

//            $logOutPackageData[$key]['storage_manage_id'] = $storageManageInfo['id'];//库存id
//            $logOutPackageData[$key]['materiel_class_id'] = $materielTypeInfo['materiel_class_id'];//物料二级分类主键名称
//            $logOutPackageData[$key]['materiel_type_id'] = $materielTypeInfo['id'];//物料id
//            $logOutPackageData[$key]['storage_id'] = $storageInfo['id'];//仓库主键id
//            $logOutPackageData[$key]['out_time'] = strtotime(date('Y-m-d'));//实际出库时间
//            $logOutPackageData[$key]['mean_cost'] = $storageManageInfo['materiel_mean_cost'];//物料均价

            $price = empty($value['price'])?0:$value['price'];

//            $logOutPackageData[$key]['price'] = $data['all_id_type'] == 1?$storageManageInfo['materiel_mean_cost']:$price;
//            $logOutPackageData[$key]['all_id_type'] = $data['all_id_type'];//单据类型;0:无;1:报损;2:销售;
//            $logOutPackageData[$key]['all_id'] = $data['all_id'];//单据id
//            $logOutPackageData[$key]['user_id'] = $userId;
//            $logOutPackageData[$key]['main_id'] = $mainId;
//            $logOutPackageData[$key]['created_at'] = time();
//            $logOutPackageData[$key]['num'] = $value['num'];//操作数量

            $logOutstorageData[$key]['materiel_type_id'] = $materielTypeInfo['id'];//物料id
            $logOutstorageData[$key]['materiel_name'] = $materielTypeInfo['materiel_name'];//物料名称
            $logOutstorageData[$key]['type_name'] = $materielTypeInfo['type_name'];//物料型号
            $logOutstorageData[$key]['materiel_no'] = $materielTypeInfo['materiel_no'];//物料编号
            $logOutstorageData[$key]['materiel_class_id'] = $materielTypeInfo['materiel_class_id'];//物料二级分类主键名称
            $logOutstorageData[$key]['materiel_class_name'] = $materielTypeInfo['class_name'];//物料二级分类名称
            $logOutstorageData[$key]['materiel_class_no'] = $materielTypeInfo['class_no'];//物料二级分类编号
            $logOutstorageData[$key]['curr_storage_manage_id'] = $storageManageInfo['id'];//库存id
            $logOutstorageData[$key]['type'] = 0;//type;0:出库;1:调出;
            $logOutstorageData[$key]['storage_id'] = $storageInfo['id'];//仓库主键id
            $logOutstorageData[$key]['storage_name'] = $storageInfo['storage_name'];//仓库名
            $logOutstorageData[$key]['storage_address'] = $storageInfo['storage_address'];//仓库地址
            $logOutstorageData[$key]['next_storage_id'] = 0;//调拨出库目标仓库主键id
            $logOutstorageData[$key]['shelf_id'] = $shelfInfo['shelf_id'];//货架
            $logOutstorageData[$key]['location_id'] = $shelfLocationInfo['location_id'];//库位
            $logOutstorageData[$key]['operate_num'] = $value['num'];//操作数量
            $logOutstorageData[$key]['last_storage_num'] = $storageManageInfo['in_storage_num'];//操作前库存数
            $logOutstorageData[$key]['sell_price'] = $storageManageInfo['materiel_mean_cost'];//物料均价
            $logOutstorageData[$key]['materiel_mean_cost'] = $storageManageInfo['materiel_mean_cost'];//物料均价
            $logOutstorageData[$key]['next_storage_num'] = $storageManageInfo['in_storage_num'] - $value['num'];//操作后库存数
            $logOutstorageData[$key]['all_id_type'] = $data['all_id_type'];//单据类型;0:无;1:报损;2:销售;
            $logOutstorageData[$key]['all_id'] = $data['all_id'];//单据id
            $logOutstorageData[$key]['out_storage_time'] = strtotime($data['out_storage_time']);//出库时间
            $logOutstorageData[$key]['fact_out_time'] = strtotime(date('Y-m-d'));//实际出库时间
            $logOutstorageData[$key]['remark'] = empty($data['remark'])?'':$data['remark'];//备注
            $logOutstorageData[$key]['user_id'] = $userId;//操作人用户id
            $logOutstorageData[$key]['main_id'] = $mainId;//主账号id
            $logOutstorageData[$key]['created_at'] = time();

            $outstorageNumsData[] = [
                'id' => $storageManageInfo['id'],//库存主键id
                'in_storage_num' => $storageManageInfo['in_storage_num'],//当前库存数
                'materiel_name' => $materielTypeInfo['materiel_name'],//出库物料名
                'type_name' => $materielTypeInfo['type_name'],//出库物料型号
                'alert_num' => $storageManageInfo['alert_num'],//低库存预警数
                'storage_name' => $storageInfo['storage_name'],
                'materiel_no' => $materielTypeInfo['materiel_no'],//出库物料型号
                'type_id' => $materielTypeInfo['id'],//物料id
                'num' => $value['num'],//出库数量
            ];

            $returnData[] = [
                'materiel_name' => $materielTypeInfo['materiel_name'],//物料名
                'type_name' => $materielTypeInfo['type_name'],//物料型号
                'warehouse' => $storageInfo['storage_name'],//仓库名
                'warehouse_id' => $storageInfo['id'],//仓库主键id
                'cost_price' => $storageManageInfo['materiel_mean_cost'],//平均成本价
            ];
        }

        //生成入库操作记录
        LogOutstorageModel::insert($logOutstorageData);

        //更新库存总数
        foreach($outstorageNumsData as $val) {
            StorageManageModel::where('id', $val['id'])->decrement('in_storage_num', $val['num']);

            //验证是否有预出库，有则跳过此步骤
            $prepareInfo = SellMaterielPrepareOutLogModel::where('sell_id', $sellId)
                ->where('materiel_type_id', $val['type_id'])->first();

            if(empty($prepareInfo)) {
                StorageManageModel::where('id', $val['id'])->decrement('virtual_storage_num', $val['num']);
            }

            MessageService::sendAlertSms(
                $val['materiel_name'],
                $val['type_name'],
                $val['in_storage_num'] - $val['num'],
                $val['alert_num'],
                $datas=['user_id'=>$userId,'main_id' => $mainId],
                $storageInfo['id'],
                $val['storage_name'],
                $val['num']
            );

            MessageService::sendShortSms(
                $val['materiel_name'],
                $val['type_name'],
                $val['in_storage_num'] - $val['num'],
                $datas=['user_id'=>$userId,'main_id' => $mainId],
                $val['storage_name'],
                $storageInfo['id']
            );

            MessageService::sendOutSms(
                $val['materiel_name'],
                $val['type_name'],
                $val['in_storage_num'] - $val['num'],
                $val['storage_name'],
                $val['num'],
                $datas=['user_id'=>$userId,'main_id' => $mainId],
                $storageInfo['id'],
                $val['alert_num'],
            );
        }

        return true;
    }

    /**
     * @出库
     * @created 在 2021/11/29 19:08 创建
     * @param $userId 操作人用户id
     * @param $mainId 主账号id
     * @param $data['content] 出库物料商品信息
     * @param $data['content]['name] 物料名称
     * @param $data['content]['price] 单价
     * @param $data['content]['type_name] 物料型号
     * @param $data['content]['warehouse] 仓库名
     * @param $data['content]['warehouse_id] 仓库主键id
     * @param $data['content]['num] 出库操作数量
     * @param $data['all_id_type] 单据类型;0:无;1:报损;2:销售;
     * @param $data['all_id] 单据id
     * @param $data['out_storage_time] 出库时间
     * @param $data['remark] 备注
     * @return array
     * @author: Sun Wu
     */
    static public function outStorage($userId, $mainId, $data, $sellId = 0, $isUseShelf = 0)
    {
        if(empty($data['content'])) {
            return ['code' => 1, 'msg' => '无可出库商品信息', 'data' => ''];
        }

        $logOutstorageData = [];//出库操作记录数据
        $outstorageNumsData = [];//库存数据信息-更新库存
        $returnData = [];//返回数据
        $sellGoodsList = [];

        $sellInfo = SellModel::where('id', $data['all_id'])->first();
        foreach($data['content'] as $key => $value) {
            $shelfId = empty($value['shelf_id'])?0:$value['shelf_id'];
            $locationId = empty($value['location_id'])?0:$value['location_id'];

            //物料商品信息
            $materielTypeInfo = MaterielsTypeModel::select(
                'a.id',
                'materiel_name',
                'type_name',
                'materiel_no',
                'b.id as materiel_class_id',
                'b.class_name',
                'b.class_no'
            )
                ->from('materiel_type as a')
                ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                ->where([
                    'materiel_name' => $value['name'],
                    'type_name' => $value['type_name'],
                    'a.main_id' => $mainId,
                    'a.delete_flag' => 0,
                ])
                ->first();

            if(empty($materielTypeInfo)) {
                return ['code' => 1, 'msg' => '物料`'.$value['name'].'-'.$value['type_name'].'`不存在', 'data' => ''];
            }

            //仓库信息
            $storageInfo = StorageModel::where([
                'storage_name' => $value['warehouse'],
                'id' => $value['warehouse_id'],
                'main_id' => $mainId,
                'delete_flag' => 0,
            ])->first();

            if(empty($storageInfo)) {
                return ['code' => 1, 'msg' => '仓库`'.$value['warehouse'].'`不存在', 'data' => ''];
            }

            //物料当前库存信息
            if($isUseShelf) {
                $storageManageInfo = StorageManageModel::where([
                    'type_id' => $materielTypeInfo['id'],
                    'storage_id' => $storageInfo['id'],
                    'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                    'main_id' => $mainId,
                    'delete_flag' => 0,
                    'shelf_id' => $shelfId,
                    'location_id' => $locationId,
                ])->first();
            }
            else {
                $storageManageInfo = StorageManageModel::where([
                    'type_id' => $materielTypeInfo['id'],
                    'storage_id' => $storageInfo['id'],
                    'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                    'main_id' => $mainId,
                    'delete_flag' => 0,
                ])->first()->toArray();
            }

            //检查库存中是否存在该物料
            if(empty($storageManageInfo)) {
                return ['code' => 1, 'msg' => '库存中物料`'.$value['name'].'-'.$value['type_name'].'`不存在', 'data' => ''];
            }

            if($storageManageInfo['in_storage_num'] < $value['num']) {
                return ['code' => 1, 'msg' => $value['name'].'-'.$value['type_name'].'当前库存剩余数量'.$storageManageInfo['in_storage_num'].'不足，无法完成出库', 'data' => ''];
            }

            $logOutstorageData[$key]['materiel_type_id'] = $materielTypeInfo['id'];//物料id
            $logOutstorageData[$key]['materiel_name'] = $materielTypeInfo['materiel_name'];//物料名称
            $logOutstorageData[$key]['type_name'] = $materielTypeInfo['type_name'];//物料型号
            $logOutstorageData[$key]['materiel_no'] = $materielTypeInfo['materiel_no'];//物料编号
            $logOutstorageData[$key]['materiel_class_id'] = $materielTypeInfo['materiel_class_id'];//物料二级分类主键名称
            $logOutstorageData[$key]['materiel_class_name'] = $materielTypeInfo['class_name'];//物料二级分类名称
            $logOutstorageData[$key]['materiel_class_no'] = $materielTypeInfo['class_no'];//物料二级分类编号
            $logOutstorageData[$key]['curr_storage_manage_id'] = $storageManageInfo['id'];//库存id
            $logOutstorageData[$key]['type'] = 0;//type;0:出库;1:调出;
            $logOutstorageData[$key]['storage_id'] = $storageInfo['id'];//仓库主键id
            $logOutstorageData[$key]['storage_name'] = $storageInfo['storage_name'];//仓库名
            $logOutstorageData[$key]['storage_address'] = $storageInfo['storage_address'];//仓库地址
            $logOutstorageData[$key]['next_storage_id'] = 0;//调拨出库目标仓库主键id
            $logOutstorageData[$key]['operate_num'] = $value['num'];//操作数量
            $logOutstorageData[$key]['last_storage_num'] = $storageManageInfo['in_storage_num'];//操作前库存数
            $logOutstorageData[$key]['sell_price'] = $value['price'];//物料均价
            $logOutstorageData[$key]['materiel_mean_cost'] = $storageManageInfo['materiel_mean_cost'];//物料均价
            $logOutstorageData[$key]['next_storage_num'] = $storageManageInfo['in_storage_num'] - $value['num'];//操作后库存数
            $logOutstorageData[$key]['all_id_type'] = $data['all_id_type'];//单据类型;0:无;1:报损;2:销售;
            $logOutstorageData[$key]['all_id'] = $data['all_id'];//单据id
            $logOutstorageData[$key]['out_storage_time'] = strtotime($data['out_storage_time']);//出库时间
            $logOutstorageData[$key]['fact_out_time'] = strtotime(date('Y-m-d'));//实际出库时间
            $logOutstorageData[$key]['remark'] = empty($data['remark'])?'':$data['remark'];//备注
            $logOutstorageData[$key]['user_id'] = $userId;//操作人用户id
            $logOutstorageData[$key]['main_id'] = $mainId;//主账号id
            $logOutstorageData[$key]['shelf_id'] = $shelfId;
            $logOutstorageData[$key]['location_id'] = $locationId;
            $logOutstorageData[$key]['created_at'] = time();
            $logOutstorageData[$key]['serial_number'] = $value['serial_no'];
            $sellGoodsList[] = [
                'materiel_type_id' => $materielTypeInfo['id'],
                'cost_price' => $storageManageInfo['materiel_mean_cost'],
                'num' => $value['num'],
                'main_id' => $mainId,
//                'user_id' => $userId,
                'sell_id' => $data['all_id'],
                'sell_date' => strtotime($sellInfo['sell_date']),
                'created_at' => time(),
            ];

            $logOutstorageData[$key]['shelf_id'] = $shelfId;
            $logOutstorageData[$key]['location_id'] = $locationId;

            $outstorageNumsData[] = [
                'id' => $storageManageInfo['id'],//库存主键id
                'in_storage_num' => $storageManageInfo['in_storage_num'],//当前库存数
                'materiel_name' => $materielTypeInfo['materiel_name'],//出库物料名
                'type_name' => $materielTypeInfo['type_name'],//出库物料型号
                'alert_num' => $storageManageInfo['alert_num'],//低库存预警数
                'storage_name' => $storageInfo['storage_name'],
                'materiel_no' => $materielTypeInfo['materiel_no'],//出库物料型号
                'type_id' => $materielTypeInfo['id'],//物料id
                'num' => $value['num'],//出库数量
                'shelf_id' => empty($value['shelf_id'])?'':$value['shelf_id'],
                'location_id' =>  empty($value['location_id'])?'':$value['location_id'],

            ];

            $returnData[] = [
                'materiel_name' => $materielTypeInfo['materiel_name'],//物料名
                'type_name' => $materielTypeInfo['type_name'],//物料型号
                'warehouse' => $storageInfo['storage_name'],//仓库名
                'warehouse_id' => $storageInfo['id'],//仓库主键id
                'cost_price' => $storageManageInfo['materiel_mean_cost'],//平均成本价
            ];
        }

        DB::beginTransaction();

        try {
            //生成入库操作记录
            LogOutstorageModel::insert($logOutstorageData);

            //更新库存总数
            foreach($outstorageNumsData as $val) {
                StorageManageModel::where('id', $val['id'])->decrement('in_storage_num', $val['num']);

                //验证是否有预出库，有则跳过此步骤
                if($sellId != 0) {
//                    $prepareInfo = SellMaterielPrepareOutLogModel::where('sell_id', $sellId)
//                        ->where('materiel_type_id', $val['type_id'])->first();
                    $prepareInfo = SellMaterielPrepareOutLogModel::where('sell_id', $sellId)
                        ->where('materiel_type_id', $val['type_id'])->where(['shelf_id' => $shelfId,'location_id' => $locationId])->first();
                    if(empty($prepareInfo)) {
                        StorageManageModel::where('id', $val['id'])->decrement('virtual_storage_num', $val['num']);
                    }
                }

                MessageService::sendAlertSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['num'],
                    $val['alert_num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $storageInfo['id'],
                    $val['storage_name'],
                    $val['num']
                );

                MessageService::sendShortSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $val['storage_name'],
                    $storageInfo['id']
                );

                MessageService::sendOutSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['num'],
                    $val['storage_name'],
                    $val['num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $storageInfo['id'],
                    $val['alert_num'],
                );
            }

            SellGoodsListModel::insert($sellGoodsList);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => $returnData];
        }
        catch(Exception $e) {
            DB::rollback();
            Log::debug('出库：'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '出库失败！', 'data' => ''];
        }
    }

    /**
     *
     * @param $userId 操作人用户id
     * @param $mainId 主账号id
     * @param $data['content] 出库物料商品信息
     * @param $data['content]['storage_manage_id] 商品库存id
     * @param $data['content]['price] 单价
     * @param $data['content]['num] 出库操作数量
     * @param $data['content]['batch_info] 批次信息
     * @param $data['all_id_type] 单据类型;0:无;1:报损;2:销售;
     * @param $data['all_id] 单据id
     * @param $data['out_storage_time] 出库时间
     * @param $data['remark] 备注
     * @return array
     * @author: Sun Wu
     */
    static public function outStorageWithBatch($userId, $mainId, $data, $sellId)
    {
        foreach($data['content'] as $value) {
            foreach($value['batch_info'] as $val) {
                //出库商品基础信息
                $storageManageInfo = StorageManageModel::select(
                    'a.id',
                    'a.storage_id',
                    'b.storage_name',
                    'b.storage_address',
                    'a.type_id',
                    'c.materiel_name',
                    'c.materiel_no',
                    'c.type_name',
                    'a.materiel_class_id',
                    'd.class_name',
                    'd.class_no',
                    'materiel_mean_cost',
                    'in_storage_num'
                )
                    ->from('storage_manage as a')
                    ->leftJoin('storage as b', 'b.id', '=', 'a.storage_id')
                    ->leftJoin('materiel_type as c', 'c.id', '=', 'a.type_id')
                    ->leftJoin('materiel_class as d', 'd.id', '=', 'c.materiel_class_id')
                    ->where([
                        'a.id' => $val['storage_manage_id'],
                        'a.delete_flag' => 0
                    ])->first();

                MessageService::sendAlertSms(
                    $storageManageInfo['materiel_name'],
                    $storageManageInfo['type_name'],
                    $storageManageInfo['in_storage_num'] - $val['num'],
                    $storageManageInfo['alert_num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $storageManageInfo['storage_id'],
                    $storageManageInfo['storage_name'],
                    $val['num']
                );

                MessageService::sendShortSms(
                    $storageManageInfo['materiel_name'],
                    $storageManageInfo['type_name'],
                    $storageManageInfo['in_storage_num'] - $val['num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $storageManageInfo['storage_name'],
                    $storageManageInfo['storage_id']
                );

                MessageService::sendOutSms(
                    $storageManageInfo['materiel_name'],
                    $storageManageInfo['type_name'],
                    $storageManageInfo['in_storage_num'] - $val['num'],
                    $storageManageInfo['storage_name'],
                    $val['num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $storageManageInfo['storage_id'],
                    $storageManageInfo['alert_num']
                );

                $outStorageLogInfo[] = [
                    'storage_id' => $storageManageInfo['storage_id'],
                    'storage_name' => $storageManageInfo['storage_name'],
                    'storage_address' => $storageManageInfo['storage_address'],
                    'curr_storage_manage_id' => $storageManageInfo['id'],
                    'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                    'materiel_class_name' => $storageManageInfo['class_name'],
                    'materiel_class_no' => $storageManageInfo['class_no'],
                    'materiel_type_id' => $storageManageInfo['type_id'],
                    'materiel_name' => $storageManageInfo['materiel_name'],
                    'type_name' => $storageManageInfo['type_name'],
                    'materiel_no' => $storageManageInfo['materiel_no'],
                    'operate_num' => $val['num'],
                    'last_storage_num' => $storageManageInfo['in_storage_num'],
                    'next_storage_num' => $storageManageInfo['in_storage_num'] - $val['num'],
                    'materiel_mean_cost' => $storageManageInfo['materiel_mean_cost'],
                    'all_id_type' => 2,
                    'all_id' => $sellId,
                    'user_id' => $userId,
                    'user_id' => $userId,
                    'main_id' => $mainId,
                    'remark' => $value['remark'],
                    'out_storage_time' => $value['in_storage_time'],
                    'fact_out_time' => time(),
                    'created_at' => time(),
                    'storage_batch_id' => $val['batch_id'],
                ];

                $logOutPackageInfo[] = [
                    'storage_manage_id' => $storageManageInfo['id'],
                    'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                    'materiel_type_id' => $storageManageInfo['type_id'],
                    'storage_id' => $storageManageInfo['storage_id'],
                    'out_time' => $value['in_storage_time'],
                    'num' => $val['num'],
                    'mean_cost' => $storageManageInfo['materiel_mean_cost'],
                    'price' => $value['price'],
                    'all_id_type' => 2,
                    'all_id' => $sellId,
                    'user_id' => $userId,
                    'main_id' => $mainId,
                    'created_at' => time(),
                ];

                $outStorageInfo[] = [
                    'id' =>  $storageManageInfo['id'],
                    'num' => $val['num'],
                ];

                $batchInfo[] = [
                    'id' => $val['batch_id'],
                    'num' => $val['num'],
                ];
            }
        }

        return [
            'data' => $outStorageLogInfo,
            'data1' => $logOutPackageInfo,
            'data2' => $outStorageInfo,
            'data3' => $batchInfo,
        ];
    }

    /**出库撤销回滚数量
     * @created 在 2022/01/11 10:17 创建
     * @param $allIdType 单据类型;1:报损;2:销售;
     * @param $allId 对应单据主键id
     * @return 0:商品被删除，无法撤销;1:撤销成功;
     * @author: Sun Wu
     */
    static public function cancelOut($allIdType, $allId)
    {
        $logOutInfo = LogOutstorageModel::where([
            'all_id_type' => $allIdType,
            'all_id' => $allId,
            'is_cancel' => 0
        ])->get()->toArray();

        if(!empty($logOutInfo)) {
            $item = [];
            foreach($logOutInfo as $value) {
                if(!isset($item[$value['curr_storage_manage_id']])) {
                    $item[$value['curr_storage_manage_id']] = [
                        'id' => $value['curr_storage_manage_id'],
                        'num' => $value['operate_num']
                    ];
                }
                else {
                    $item[$value['curr_storage_manage_id']]['num'] += $value['operate_num'];
                }
            }

            $logInfoId = [];
            foreach($logOutInfo as $val) {
                $logInfoId[] = $val['id'];
            }

            foreach($item as $v) {
                $checkStorageManageInfo = StorageManageModel::where([
                    'id' => $v['id'],
                    'delete_flag' => 0
                ])->first();

                if(empty($checkStorageManageInfo)) {
                    return 0;
                }

                StorageManageModel::where([
                    'id' => $v['id']
                ])->increment('in_storage_num', $v['num']);
                StorageManageModel::where([
                    'id' => $v['id']
                ])->increment('virtual_storage_num', $v['num']);
            }

            LogOutstorageModel::whereIn('id', $logInfoId)->update(['is_cancel' => 1]);
            LogOutPackageModel::where([
                'all_id_type' => $allIdType,
                'all_id' => $allId
            ])->update(['is_cancel' => 1]);
        }

        return 1;
    }

    static public function cancelPackageOut($allIdType, $allId)
    {
        $logPackageInfo = LogPackageModel::where('all_id_type', $allIdType)
            ->where('all_id', $allId)->where('is_cancel', 0)->first();

        if(!empty($logPackageInfo)) {
            $logPackageContentInfo = LogPackageContentModel::where([
                'all_id_type' => 4,
                'all_id' => $allId
            ])->get()->toArray();

            foreach($logPackageContentInfo as $value) {
                StorageManageModel::where('id', $value['out_storage_manage_id'])
                    ->update([
                        'delete_flag' => 0,
                        'in_storage_num' => DB::raw('in_storage_num +'.$value['operate_num']),
                        'virtual_storage_num' => DB::raw('virtual_storage_num +'.$value['operate_num']),
                    ]);
            }
        }

        LogPackageModel::where('all_id_type', $allIdType)
            ->where('all_id', $allId)
            ->update(['is_cancel' => 1]);

        return 1;
    }

    /**入库撤销回滚数量
     * @created 在 2022/01/11 10:47 创建
     * @param $allIdType 单据类型;1:报溢;2:退货;3:采购;
     * @param $allId 对应单据主键id
     * @return 0:商品被删除，无法撤销;1:撤销成功;2:库存数量不足，无法撤销;
     * @author: Sun Wu
     */
    static public function cancelIn($allIdType, $allId)
    {
        $logInInfo = LogInstorageModel::where([
            'all_id_type' => $allIdType,
            'all_id' => $allId,
            'is_cancel' => 0
        ])->get()->toArray();

        if(!empty($logInInfo)) {
            $item = [];
            foreach($logInInfo as $value) {
                if(!isset($item[$value['curr_storage_manage_id']])) {
                    $item[$value['curr_storage_manage_id']] = [
                        'id' => $value['curr_storage_manage_id'],
                        'num' => $value['operate_num']
                    ];
                }
                else {
                    $item[$value['curr_storage_manage_id']]['num'] += $value['operate_num'];
                }
            }

            $logInfoId = [];
            foreach($logInInfo as $val) {
                $logInfoId[] = $val['id'];
            }

            foreach($item as $v) {
                $checkStorageManageInfo = StorageManageModel::where([
                    'id' => $v['id'],
                    'delete_flag' => 0
                ])->first();

                if(empty($checkStorageManageInfo)) {
                    return 0;
                }

                if($checkStorageManageInfo['in_storage_num'] < $v['num']) {
                    return 2;
                }

                StorageManageModel::where([
                    'id' => $v['id']
                ])
                    ->update([
                        'virtual_storage_num' => DB::raw('virtual_storage_num - '.$v['num']),
                        'in_storage_num' => DB::raw('in_storage_num - '.$v['num']),
                    ]);
            }

            LogInstorageModel::whereIn('id', $logInfoId)->update(['is_cancel' => 1]);
        }

        return 1;
    }

    static public function cancelPackageIn($type, $id)
    {
        $logPackageInfo = LogPackageModel::where(['all_id_type' => $type, 'all_id' => $id, 'is_cancel' => 0])
            ->first();

        try {
            if(!empty($logPackageInfo)) {
                $logPackageContentInfo = LogPackageContentModel::where([
                    'all_id_type' => 5,
                    'all_id' => $id,
                ])
                    ->get()->toArray();

                foreach($logPackageContentInfo as $value) {
                    $storageManageInfo = StorageManageModel::where([
                        'id' => $value['out_storage_manage_id'],
                        'delete_flag' => 0
                    ])
                        ->first()->toArray();
                    //库存中无此商品
                    if(empty($storageManageInfo)) {
                        return 0;
                    }

                    //库存数不足
                    if($storageManageInfo['in_storage_num'] < $value['operate_num']) {
                        return 3;
                    }

                    StorageManageModel::where('id', $value['out_storage_manage_id'])
                        ->update([
                            'in_storage_num' => DB::raw('in_storage_num - '.$value['operate_num']),
                            'virtual_storage_num' => DB::raw('virtual_storage_num - '.$value['operate_num']),
                        ]);
                }
            }

            LogPackageModel::where(['all_id_type' => $type, 'all_id' => $id, 'is_cancel' => 0])
                ->update(['is_cancel' => 1]);

            DB::commit();
            return 1;
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('套餐入库撤销异常:'.var_export($e->getMessage(), true));
            return 2;
        }
    }

    /**
     * @入库
     * @created 在 2021/11/29 19:00 创建
     * @param $userId 操作人用户id
     * @param $mainId 主账号id
     * @param array $data['content] 入库物料商品信息
     * @param array $data['content]['name'] 物料名称
     * @param array $data['content]['type_name'] 物料名称
     * @param array $data['content]['warehouse'] 仓库名
     * @param array $data['content]['warehouse_id'] 仓库主键id
     * @param array $data['content]['num] 操作数量
     * @param array $data['in_storage_time] 入库时间
     * @param array $data['all_id_type] 单据类型;0:无;1:报溢;2:退货;3:采购;
     * @param array $data['all_id] 单据id
     * @param array $data['remark] 备注
     * @return array
     * @author: ZLF
     */
    static public function zongInStorage($userId, $mainId, $data,$flag = 0)
    {
        $logInstorageData = [];//入库操作记录数据
        $instorageNumsData = [];//库存数据信息-更新库存
        $arr = [];
        foreach($data['content'] as $key => $value) {

            //为了兼容版本 判断shelf_id 和location_id
            if(empty($value['shelf_id']) || empty($value['location_id'])){
                /*  $shelf_id = ShelfService::get_default($value['warehouse_id'])['id'];
                 $location_id = ShelfService::get_default($shelf_id,2)['id']; */
                $sfData = ShelfService::get_default($value['warehouse_id']);
                if(!empty($sfData)){
                    $shelf_id = $sfData['id'];
                    $lData = ShelfService::get_default($shelf_id,2);
                    $location_id = $lData['id'];
                }else{
                    $shelf_id = 0;
                    $location_id = 0;
                    $value['shelf_id']=0;
                    $value['location_id']=0;
                }
            }else{
                $shelf_id = $value['shelf_id'];
                $location_id = $value['location_id'];
            }

            //物料商品信息
            $materielTypeInfo = MaterielTypeModel::select(
                'a.id',
                'materiel_name',
                'type_name',
                'materiel_no',
                'b.id as materiel_class_id',
                'b.class_name',
                'b.class_no',
                'c.id as first_class'
                )
                ->from('materiel_type as a')
                ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id')
                ->where([
                    'a.id' => $value['goods_id'],
                    'materiel_name' => $value['name'],
                    'type_name' => $value['type_name'],
                    'a.main_id' => $mainId
                ])
                ->first();

                if(empty($materielTypeInfo)) {
                    throw new Exception('商品信息不存在，无法入库');
                }

                //仓库信息
                $storageInfo = StorageModel::where([
                    'storage_name' => $value['warehouse'],
                    'id' => $value['warehouse_id'],
                    'main_id' => $mainId,
                    'delete_flag' => 0,
                ])->first();

                //物料当前库存信息
                $storageManageInfo = StorageManageModel::where([
                    'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                    'type_id' => $materielTypeInfo['id'],
                    'storage_id' => $storageInfo['id'],
                    'main_id' => $mainId,
                    'shelf_id' => $shelf_id,
                    'location_id' => $location_id
                ])->first();

                if(empty($storageManageInfo)) {
                    $arr[] = [
                        'first_class' => $materielTypeInfo['first_class'],
                        'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                        'materiel_class_name' => $materielTypeInfo['class_name'],
                        'materiel_class_no' => $materielTypeInfo['class_no'],
                        'type_id' => $materielTypeInfo['id'],
                        'materiel_name' => $materielTypeInfo['materiel_name'],
                        'type_name' => $materielTypeInfo['type_name'],
                        'materiel_no' => $materielTypeInfo['materiel_no'],
                        'storage_id' => $storageInfo['id'],
                        'storage_name' => $storageInfo['storage_name'],
                        'storage_address' => $storageInfo['storage_address'],
                        'in_storage_num' => $value['num'],
                        'virtual_storage_num' => $value['num'],
                        'main_id' => $mainId,
                        'in_storage_time' => time(),

                        'shelf_id' => $shelf_id,
                        'location_id' => $location_id,
                        'serial_no' => empty($value['serial_no'])?'':$value['serial_no'],
                    ];

                    MessageService::sendInSms(
                        '',
                        $materielTypeInfo['materiel_name'],
                        $materielTypeInfo['type_name'],
                        $storageInfo['id'],
                        $storageInfo['storage_name'],
                        $datas=['user_id'=>$userId,'main_id' => $mainId],
                        $value['num'],
                        $value['num']
                        );
                }else {

                    if(!empty($value['serial_no'])){

                        $instorageNumsData[] = [
                            'id' => $storageManageInfo['id'],//库存主键id
                            'in_storage_num' => $value['num'],//入库数量
                            'type_id' => $materielTypeInfo['id'],
                            'cost' => $storageManageInfo['materiel_mean_cost'],
                            'serial_no' => $value['serial_no'],
                        ];
                    }else{

                        $instorageNumsData[] = [
                            'id' => $storageManageInfo['id'],//库存主键id
                            'in_storage_num' => $value['num'],//入库数量
                            'type_id' => $materielTypeInfo['id'],
                            'cost' => $storageManageInfo['materiel_mean_cost']
                        ];
                    }

                    MessageService::sendInSms(
                        '',
                        $materielTypeInfo['materiel_name'],
                        $materielTypeInfo['type_name'],
                        $storageInfo['id'],
                        $storageInfo['storage_name'],
                        $datas=['user_id'=>$userId,'main_id' => $mainId],
                        $value['num'],
                        $value['num'] + $storageManageInfo['in_storage_num']
                        );

                    $logInstorageData[$key]['curr_storage_manage_id'] = $storageManageInfo['id'];//当前库存id
                }

                $logInstorageData[$key]['materiel_type_id'] = $materielTypeInfo['id'];//物料id
                $logInstorageData[$key]['materiel_name'] = $materielTypeInfo['materiel_name'];//物料名称
                $logInstorageData[$key]['type_name'] = $materielTypeInfo['type_name'];//物料型号
                $logInstorageData[$key]['materiel_no'] = $materielTypeInfo['materiel_no'];//物料编号

                $logInstorageData[$key]['materiel_class_id'] = $materielTypeInfo['materiel_class_id'];//物料二级分类主键名称
                $logInstorageData[$key]['materiel_class_name'] = $materielTypeInfo['class_name'];//物料二级分类名称
                $logInstorageData[$key]['materiel_class_no'] = $materielTypeInfo['class_no'];//物料二级分类编号
                $logInstorageData[$key]['type'] = 0;//入库日志类型;0:入库;1:调拨入库;2:直接入库;

                $logInstorageData[$key]['storage_id'] = $storageInfo['id'];//仓库主键id
                $logInstorageData[$key]['storage_name'] = $storageInfo['storage_name'];//仓库名
                $logInstorageData[$key]['storage_address'] = $storageInfo['storage_address'];//仓库地址
                $logInstorageData[$key]['last_storage_id'] = 0;//调拨前所在仓库id

                $logInstorageData[$key]['operate_num'] = $value['num'];//操作数量

                $logInstorageData[$key]['last_storage_num'] = empty($storageManageInfo['in_storage_num'])?0:$storageManageInfo['in_storage_num'];//操作前库存数

                $logInstorageData[$key]['materiel_mean_cost'] = empty($storageManageInfo['materiel_mean_cost'])?0:$storageManageInfo['materiel_mean_cost'];//物料均价

                if(!empty($storageManageInfo)){
                    $logInstorageData[$key]['next_storage_num'] = $storageManageInfo['in_storage_num'] + $value['num'];//操作后库存数
                }else{
                    $logInstorageData[$key]['next_storage_num'] = $value['num'];//操作后库存数

                }
                $logInstorageData[$key]['all_id_type'] = $data['all_id_type'];//单据类型;0:无;1:报溢;2:退货;3:采购;
                $logInstorageData[$key]['in_storage_time'] = strtotime($data['in_storage_time']);//入库时间
                $logInstorageData[$key]['all_id'] = $data['all_id'];//单据id
                $logInstorageData[$key]['user_id'] = $userId;//操作人用户id
                $logInstorageData[$key]['main_id'] = $mainId;//主账号id
                $logInstorageData[$key]['remark'] = empty($data['remark'])?'':$data['remark'];
                $logInstorageData[$key]['created_at'] = time();
                $logInstorageData[$key]['serial_number'] = !empty($value['serial_no'])?$value['serial_no']:'';
                $logInstorageData[$key]['shelf_id'] = $shelf_id;
                $logInstorageData[$key]['location_id'] = $location_id;

        }

        DB::beginTransaction();

        try {

            if(!empty($instorageNumsData)) {

                //更新库存总数
                foreach($instorageNumsData as $key => $value) {
                    $bool = StorageManageModel::where('id', $value['id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num + '.$value['in_storage_num']),
                        'virtual_storage_num' => DB::raw('virtual_storage_num + '.$value['in_storage_num']),
                        'delete_flag' => 0
                    ]);

                    $batchTitle = empty($data['batch_title']) ? '' : $data['batch_title'];
                    $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                    $checkBatchNo = StorageBatchModel::where('main_id', $mainId)
                    ->where('batch_no', $batchNo)->first();

                    do {
                        $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                    }
                    while(!empty($checkBatchNo));

                    $batchId = MaterielService::createBatchInfoGetId(
                        $batchNo,
                        $value['id'],
                        $value['cost'],
                        $value['in_storage_num'],
                        0,
                        $mainId
                        );
//                    if(!$flag){
                        if(!empty($value['serial_no'])){
                            //处理序列号
                            $serialData = array_filter(
                                explode(',', $value['serial_no']), function($v) { return $v !== ''; }
                            );

                            $checkSerialNumber = SerialNumberModel::where('goods_id', $value['type_id'])
                                ->where('status', 1)
                                ->whereIn('serial_no', $serialData)
                                ->first();

                            if(!empty($checkSerialNumber)) {
                                throw new Exception('序列号:'.$checkSerialNumber['serial_no'.'未出库，无法退货']);
                            }

                            SerialNumberModel::where('goods_id', $value['type_id'])
                                ->whereIn('serial_no', $serialData)->update(['status' => 1]);

//                            $serial_no_res = SerialNumberModel::inSerialNumber($mainId,$value['serial_no'],$value['in_storage_num'],$value['type_id'],$value['id'],$batchNo);
                            if(!empty($serial_no_res['code'])){
                                return ['code' => 1, 'msg' => $serial_no_res['msg'], 'data' => ''];
                            }
                        }
//                    }
                }
            }

            if(!empty($arr)) {
                foreach($arr as $v) {
                    foreach($logInstorageData as $k1 => $v1) {
                        if($v1['materiel_type_id'] == $v['type_id']) {
                            $arr = [
                                'materiel_class_id' => $v['materiel_class_id'],
                                'materiel_class_name' => $v['materiel_class_name'],
                                'materiel_class_no' => $v['materiel_class_no'],
                                'type_id' => $v['type_id'],
                                'materiel_name' => $v['materiel_name'],
                                'type_name' => $v['type_name'],
                                'materiel_no' => $v['materiel_no'],
                                'storage_id' => $v['storage_id'],
                                'storage_name' => $v['storage_name'],
                                'storage_address' => $v['storage_address'],
                                'in_storage_num' => $v['in_storage_num'],
                                'virtual_storage_num' => $v['virtual_storage_num'],
                                'main_id' => $mainId,
                                'in_storage_time' => time(),

                                'shelf_id' => $v['shelf_id'],
                                'location_id' => $v['location_id'],
                            ];

                            $batchTitle = empty($data['batch_title']) ? '' : $data['batch_title'];
                            $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                            $checkBatchNo = StorageBatchModel::where('main_id', $mainId)
                            ->where('batch_no', $batchNo)->first();

                            do {
                                $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                            }
                            while(!empty($checkBatchNo));

                            $insertId = StorageManageModel::insertGetId($arr);

                            $logInstorageData[$k1]['curr_storage_manage_id'] = $insertId;

                            $batchId = MaterielService::createBatchInfoGetId(
                                $batchNo,
                                $insertId,
                                0,
                                $v['in_storage_num'],
                                0,
                                $mainId
                                );

                            $logInstorageData[$k1]['batch_id'] = $batchId;
//                            if(!$flag){
                                if(!empty($v['serial_no'])){
                                    //处理序列号
                                    $serial_no_res = SerialNumberModel::inSerialNumber($mainId,$v['serial_no'],$v['in_storage_num'],$v['type_id'],$insertId,$batchNo);
                                    if(!empty($serial_no_res['code'])){
                                        return ['code' => 1, 'msg' => $serial_no_res['msg'], 'data' => ''];
                                    }
                                }
                            }
//                        }
                    }
                }
            }

            if(!empty($logInstorageData)){
                foreach ($logInstorageData as &$lv){
                    if(empty($lv['batch_id'])) $lv['batch_id'] = 0;
                }
            }
            //生成入库操作记录
            $bool= LogInstorageModel::insert($logInstorageData);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollback();
            Log::debug('非采购入库：'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '入库失败！', 'data' => ''];
        }
    }

    /**
     * @入库
     * @created 在 2021/11/29 19:00 创建
     * @param $userId 操作人用户id
     * @param $mainId 主账号id
     * @param array $data['content] 入库物料商品信息
     * @param array $data['content]['name'] 物料名称
     * @param array $data['content]['type_name'] 物料名称
     * @param array $data['content]['warehouse'] 仓库名
     * @param array $data['content]['warehouse_id'] 仓库主键id
     * @param array $data['content]['num] 操作数量
     * @param array $data['in_storage_time] 入库时间
     * @param array $data['all_id_type] 单据类型;0:无;1:报溢;2:退货;3:采购;
     * @param array $data['all_id] 单据id
     * @param array $data['remark] 备注
     * @return array
     * @author: Sun Wu
     */
    static public function oldInStorage($userId, $mainId, $data,$flag = 0)
    {
        $logInstorageData = [];//入库操作记录数据
        $instorageNumsData = [];//库存数据信息-更新库存
        $arr = [];
        foreach($data['content'] as $key => $value) {

            //为了兼容版本 判断shelf_id 和location_id
            if(empty($value['shelf_id']) || empty($value['location_id'])){
                /*  $shelf_id = ShelfService::get_default($value['warehouse_id'])['id'];
                 $location_id = ShelfService::get_default($shelf_id,2)['id']; */
                $sfData = ShelfService::get_default($value['warehouse_id']);
                if(!empty($sfData)){
                    $shelf_id = $sfData['id'];
                    $lData = ShelfService::get_default($shelf_id,2);
                    $location_id = $lData['id'];
                }else{
                    $shelf_id = 0;
                    $location_id = 0;
                    $value['shelf_id']=0;
                    $value['location_id']=0;
                }
            }else{
                $shelf_id = $value['shelf_id'];
                $location_id = $value['location_id'];
            }

            //物料商品信息
            $materielTypeInfo = MaterielTypeModel::select(
                'a.id',
                'materiel_name',
                'type_name',
                'materiel_no',
                'b.id as materiel_class_id',
                'b.class_name',
                'b.class_no',
                'c.id as first_class'
            )
                ->from('materiel_type as a')
                ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id')
                ->where([
                    'a.id'=>$value['goods_id'],
                    'materiel_name' => $value['name'],
                    'type_name' => $value['type_name'],
                    'a.main_id' => $mainId,
                ])
                ->first();


            if(empty($materielTypeInfo)) {
                throw new Exception('商品信息不存在，无法入库');
            }

            //仓库信息
            $storageInfo = StorageModel::where([
                'storage_name' => $value['warehouse'],
                'id' => $value['warehouse_id'],
                'main_id' => $mainId,
                'delete_flag' => 0,
            ])->first();

            //物料当前库存信息
            $storageManageInfo = StorageManageModel::where([
                'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                'type_id' => $materielTypeInfo['id'],
                'storage_id' => $storageInfo['id'],
                'main_id' => $mainId,
                'shelf_id' => $shelf_id,
                'location_id' => $location_id
            ])->first();

            if(empty($storageManageInfo)) {
                $arr[] = [
                    'first_class' => $materielTypeInfo['first_class'],
                    'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                    'materiel_class_name' => $materielTypeInfo['class_name'],
                    'materiel_class_no' => $materielTypeInfo['class_no'],
                    'type_id' => $materielTypeInfo['id'],
                    'materiel_name' => $materielTypeInfo['materiel_name'],
                    'type_name' => $materielTypeInfo['type_name'],
                    'materiel_no' => $materielTypeInfo['materiel_no'],
                    'storage_id' => $storageInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'in_storage_num' => $value['num'],
                    'virtual_storage_num' => $value['num'],
                    'main_id' => $mainId,
                    'in_storage_time' => time(),

                    'shelf_id' => $shelf_id,
                    'location_id' => $location_id,
                    'serial_no' => empty($value['serial_no'])?'':$value['serial_no'],
                ];

                MessageService::sendInSms(
                    '',
                    $materielTypeInfo['materiel_name'],
                    $materielTypeInfo['type_name'],
                    $storageInfo['id'],
                    $storageInfo['storage_name'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $value['num'],
                    $value['num']
                );
            }else {

                if(!empty($value['serial_no'])){

                    $instorageNumsData[] = [
                        'id' => $storageManageInfo['id'],//库存主键id
                        'in_storage_num' => $value['num'],//入库数量
                        'type_id' => $materielTypeInfo['id'],
                        'cost' => $storageManageInfo['materiel_mean_cost'],
                        'serial_no' => $value['serial_no'],
                    ];
                }else{

                    $instorageNumsData[] = [
                        'id' => $storageManageInfo['id'],//库存主键id
                        'in_storage_num' => $value['num'],//入库数量
                        'type_id' => $materielTypeInfo['id'],
                        'cost' => $storageManageInfo['materiel_mean_cost'],
                        'serial_no' => $value['serial_no'],
                    ];
                }

               MessageService::sendInSms(
                   '',
                    $materielTypeInfo['materiel_name'],
                   $materielTypeInfo['type_name'],
                   $storageInfo['id'],
                   $storageInfo['storage_name'],
                  $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $value['num'],
                   $value['num'] + $storageManageInfo['in_storage_num']
               );

                $logInstorageData[$key]['curr_storage_manage_id'] = $storageManageInfo['id'];//当前库存id
            }

            $logInstorageData[$key]['materiel_type_id'] = $materielTypeInfo['id'];//物料id
            $logInstorageData[$key]['materiel_name'] = $materielTypeInfo['materiel_name'];//物料名称
            $logInstorageData[$key]['type_name'] = $materielTypeInfo['type_name'];//物料型号
            $logInstorageData[$key]['materiel_no'] = $materielTypeInfo['materiel_no'];//物料编号

            $logInstorageData[$key]['materiel_class_id'] = $materielTypeInfo['materiel_class_id'];//物料二级分类主键名称
            $logInstorageData[$key]['materiel_class_name'] = $materielTypeInfo['class_name'];//物料二级分类名称
            $logInstorageData[$key]['materiel_class_no'] = $materielTypeInfo['class_no'];//物料二级分类编号
            $logInstorageData[$key]['type'] = 0;//入库日志类型;0:入库;1:调拨入库;2:直接入库;

            $logInstorageData[$key]['storage_id'] = $storageInfo['id'];//仓库主键id
            $logInstorageData[$key]['storage_name'] = $storageInfo['storage_name'];//仓库名
            $logInstorageData[$key]['storage_address'] = $storageInfo['storage_address'];//仓库地址
            $logInstorageData[$key]['last_storage_id'] = 0;//调拨前所在仓库id

            $logInstorageData[$key]['operate_num'] = $value['num'];//操作数量

            $logInstorageData[$key]['last_storage_num'] = empty($storageManageInfo['in_storage_num'])?0:$storageManageInfo['in_storage_num'];//操作前库存数

            $logInstorageData[$key]['materiel_mean_cost'] = empty($storageManageInfo['materiel_mean_cost'])?0:$storageManageInfo['materiel_mean_cost'];//物料均价

           if(!empty($storageManageInfo)){
            $logInstorageData[$key]['next_storage_num'] = $storageManageInfo['in_storage_num'] + $value['num'];//操作后库存数
           }else{
            $logInstorageData[$key]['next_storage_num'] = $value['num'];//操作后库存数

           }
            $logInstorageData[$key]['all_id_type'] = $data['all_id_type'];//单据类型;0:无;1:报溢;2:退货;3:采购;
            $logInstorageData[$key]['in_storage_time'] = strtotime($data['in_storage_time']);//入库时间
            $logInstorageData[$key]['all_id'] = $data['all_id'];//单据id
            $logInstorageData[$key]['user_id'] = $userId;//操作人用户id
            $logInstorageData[$key]['main_id'] = $mainId;//主账号id
            $logInstorageData[$key]['remark'] = empty($data['remark'])?'':$data['remark'];
            $logInstorageData[$key]['created_at'] = time();
            $logInstorageData[$key]['serial_number'] = !empty($value['serial_no'])?$value['serial_no']:'';
            $logInstorageData[$key]['shelf_id'] = $shelf_id;
            $logInstorageData[$key]['location_id'] = $location_id;

        }

        DB::beginTransaction();

        try {

            if(!empty($instorageNumsData)) {

                //更新库存总数
                foreach($instorageNumsData as $key => $value) {
                    $bool = StorageManageModel::where('id', $value['id'])
                        ->update([
                            'in_storage_num' => DB::raw('in_storage_num + '.$value['in_storage_num']),
                            'virtual_storage_num' => DB::raw('virtual_storage_num + '.$value['in_storage_num']),
                            'delete_flag' => 0
                        ]);

                    $batchTitle = empty($data['batch_title']) ? '' : $data['batch_title'];
                    $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                    $checkBatchNo = StorageBatchModel::where('main_id', $mainId)
                        ->where('batch_no', $batchNo)->first();

                    do {
                        $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                    }
                    while(!empty($checkBatchNo));

                    $batchId = MaterielService::createBatchInfoGetId(
                        $batchNo,
                        $value['id'],
                        $value['cost'],
                        $value['in_storage_num'],
                        0,
                        $mainId
                    );

                    if(!empty($value['serial_no'])) {
                        $serialInfo = array_filter(
                            explode(',', $value['serial_no']), function($v) { return $v !== ''; }
                        );

                        $checkSerialNumber = SerialNumberModel::where('goods_id', $value['type_id'])
                            ->where('status', 1)
                            ->whereIn('serial_no', $serialInfo)
                            ->first();

                        if(!empty($checkSerialNumber)) {
                            throw new Exception('序列号:'.$checkSerialNumber['serial_no'.'未出库，无法退货']);
                        }

                        SerialNumberModel::where('goods_id', $value['type_id'])
                            ->whereIn('serial_no', $serialInfo)
                            ->update([
                                'status' => 1,
                                'storage_manage_id' => $value['id']
                            ]);
                    }

//                    SerialNumberModel::where('goods_id', )
//
//                    SerialNumberModel::where(['serial_no' => $serial_data,'status' => SerialNumberModel::USEDSTATUS,
//                        'goods_id' => $number_info['goods_id'],
//                    ])->update([
//                        'status' => SerialNumberModel::UNUSEDSTATUS,
//                        'storage_manage_id' => $value['id']
//                    ]);

//                    if(!$flag){
                        if(!empty($value['serial_no'])){
//                            //处理序列号
                            $serial_no_res = SerialNumberModel::inSerialNumber($mainId,$value['serial_no'],$value['in_storage_num'],$value['type_id'],$value['id'],$batchNo);
//                            if(!empty($serial_no_res['code'])){
//                                return ['code' => 1, 'msg' => $serial_no_res['msg'], 'data' => ''];
//                            }
                        }
//                    }
                }
            }

            if(!empty($arr)) {
                foreach($arr as $v) {
                    foreach($logInstorageData as $k1 => $v1) {
                        if($v1['materiel_type_id'] == $v['type_id']) {
                            $arr = [
                                'materiel_class_id' => $v['materiel_class_id'],
                                'materiel_class_name' => $v['materiel_class_name'],
                                'materiel_class_no' => $v['materiel_class_no'],
                                'type_id' => $v['type_id'],
                                'materiel_name' => $v['materiel_name'],
                                'type_name' => $v['type_name'],
                                'materiel_no' => $v['materiel_no'],
                                'storage_id' => $v['storage_id'],
                                'storage_name' => $v['storage_name'],
                                'storage_address' => $v['storage_address'],
                                'in_storage_num' => $v['in_storage_num'],
                                'virtual_storage_num' => $v['virtual_storage_num'],
                                'main_id' => $mainId,
                                'in_storage_time' => time(),

                                'shelf_id' => $v['shelf_id'],
                                'location_id' => $v['location_id'],
                            ];

                            $batchTitle = empty($data['batch_title']) ? '' : $data['batch_title'];
                            $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                            $checkBatchNo = StorageBatchModel::where('main_id', $mainId)
                                ->where('batch_no', $batchNo)->first();

                            do {
                                $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                            }
                            while(!empty($checkBatchNo));

                            $insertId = StorageManageModel::insertGetId($arr);

                            $logInstorageData[$k1]['curr_storage_manage_id'] = $insertId;

                            $batchId = MaterielService::createBatchInfoGetId(
                                $batchNo,
                                $insertId,
                                0,
                                $v['in_storage_num'],
                                0,
                                $mainId
                            );

                            $logInstorageData[$k1]['batch_id'] = $batchId;
//                            if(!$flag){
                                if(!empty($v['serial_no'])){
                                    //处理序列号
                                    $serial_no_res = SerialNumberModel::inSerialNumber($mainId,$v['serial_no'],$v['in_storage_num'],$v['type_id'],$insertId,$batchNo);
                                    if(!empty($serial_no_res['code'])){
                                        return ['code' => 1, 'msg' => $serial_no_res['msg'], 'data' => ''];
                                    }
                                }
//                            }
                        }
                    }
                }
            }

            if(!empty($logInstorageData)){
                foreach ($logInstorageData as &$lv){
                    if(empty($lv['batch_id'])) $lv['batch_id'] = 0;
                }
            }
            //生成入库操作记录
            $bool= LogInstorageModel::insert($logInstorageData);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollback();
            Log::debug('非采购入库：'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '采购入库失败 ', 'data' => ''];
        }
    }

    /**
     * @入库
     * @created 在 2021/11/29 19:00 创建
     * @modify 在 2022/05/06 16:32 By Sun Wu
     * @param $userId 操作人用户id
     * @param $mainId 主账号id
     * @param array $data['content] 入库物料商品信息
     * @param array $data['content]['name'] 物料名称
     * @param array $data['content]['type_name'] 物料名称
     * @param array $data['content]['warehouse'] 仓库名
     * @param array $data['content]['warehouse_id'] 仓库主键id
     * @param array $data['content]['num] 操作数量
     * @param array $data['in_storage_time] 入库时间
     * @param array $data['all_id_type] 单据类型;0:无;1:报溢;2:退货;3:采购;
     * @param array $data['all_id] 单据id
     * @param array $data['remark] 备注
     * @return array
     * @author: Sun Wu
     */
    static public function inStorage($isUseShelf, $userId, $mainId, $data, $batchTitle)
    {

        $logInstorageData = [];//入库操作记录数据
        $existLogInstorageData = [];
        $instorageNumsData = [];//库存数据信息-更新库存
        $arr = [];

        foreach($data['content'] as $key => $value) {
            //物料商品信息
            $materielTypeInfo = MaterielsTypeModel::select(
                'a.id',
                'materiel_name',
                'type_name',
                'materiel_no',
                'b.id as materiel_class_id',
                'b.class_name',
                'b.class_no',
                'c.id as first_class',
                'a.is_use_serial'
            )
                ->from('materiel_type as a')
                ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id')
                ->where([
                    'materiel_name' => $value['name'],
                    'type_name' => $value['type_name'],
                    'a.main_id' => $mainId,
                    'a.delete_flag' => 0,
                ])
                ->first();

            //仓库信息
            $storageInfo = StorageModel::where([
                'storage_name' => $value['warehouse'],
                'id' => $value['warehouse_id'],
                'main_id' => $mainId,
                'delete_flag' => 0,
            ])->first();

            if(!$isUseShelf || $value['shelf_id'] == 0) {
                $shelfInfo = StorageShelfModel::where('storage_id', $value['warehouse'])
                    ->where('shelf_type', 1)->first();

                $shelfLocationInfo = StorageShelfLocationModel::where('shelf_id', $shelfInfo['id'])
                    ->where('location_type', 1)->first();
            }
            else {
                $shelfInfo = StorageShelfModel::where('storage_id', $value['warehouse'])->where('id', $value['shelf_id'])->first();

                if(empty($shelfInfo)) {
                    return ['code' => 1, 'msg' => '无效货架，请重试', 'data' => ''];
                }

                $shelfLocationInfo = StorageShelfLocationModel::where('shelf_id', $value['shelf_id'])
                    ->where('shelf_location_id', $value['shelf_location_id'])->first();

                if(empty($shelfLocationInfo)) {
                    return ['code' => 1, 'msg' => '无效库位，请重试', 'data' => ''];
                }
            }

            if(empty($storageInfo)) {
                return ['code' => 1, 'msg' => '仓库`'.$value['warehouse'].'`不存在', 'data' => ''];
            }

            if(empty($materielTypeInfo)) {
                return ['code' => 1, 'msg' => '商品`'.$value['name'].'-'.$value['type_name'].'`不存在', 'data' => ''];
            }

            //物料当前库存信息
            $storageManageInfo = StorageManageModel::where([
                'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                'type_id' => $materielTypeInfo['id'],
                'storage_id' => $storageInfo['id'],
                'main_id' => $mainId,
                'delete_flag' => 0
            ])->first();

            if(empty($storageManageInfo)) {
                $arr[] = [
                    'first_class' => $materielTypeInfo['first_class'],
                    'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                    'materiel_class_name' => $materielTypeInfo['class_name'],
                    'materiel_class_no' => $materielTypeInfo['class_no'],
                    'type_id' => $materielTypeInfo['id'],
                    'materiel_name' => $materielTypeInfo['materiel_name'],
                    'type_name' => $materielTypeInfo['type_name'],
                    'materiel_no' => $materielTypeInfo['materiel_no'],
                    'storage_id' => $storageInfo['id'],
                    'shelf_id' => $shelfInfo['id'],
                    'shelf_location_id' => $shelfLocationInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'in_storage_num' => $value['num'],
                    'serial_number' => $value['serial_number'],
                    'is_use_serial' => $materielTypeInfo['is_use_serial'],
                    'main_id' => $mainId,
                    'in_storage_time' => time()
                ];
            }
            else {
                $instorageNumsData[] = [
                    'id' => $storageManageInfo['id'],//库存主键id
                    'in_storage_num' => $value['num'],//入库数量
                    'cost' => $storageManageInfo['materiel_mean_cost'],
                    'materiel_type_id' => $materielTypeInfo['id'],//物料id
                    'materiel_name' => $materielTypeInfo['materiel_name'],
                    'materiel_no' => $materielTypeInfo['materiel_no'],
                    'type_name' => $materielTypeInfo['type_name'],
                    'storage_id' => $storageInfo['id'],
                    'shelf_id' => $shelfInfo['id'],
                    'shelf_location_id' => $shelfLocationInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类主键名称
                    'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
                    'materiel_class_no' => $materielTypeInfo['class_no'],//物料二级分类编号
                    'serial_number' => $value['serial_number'],
                    'is_use_serial' => $materielTypeInfo['is_use_serial'],
                ];
            }
        }

        unset($value);

        DB::beginTransaction();
        try {
            if(!empty($instorageNumsData)) {
                //更新库存总数
                foreach($instorageNumsData as $key => $value) {
                    StorageManageModel::where('id', $value['id'])
                        ->update([
                            'in_storage_num' => DB::raw('in_storage_num +'.$value['in_storage_num']),
                            'virtual_storage_num' => DB::raw('virtual_storage_num +'.$value['in_storage_num']),
                            'delete_flag' => 0
                        ]);
                    MessageService::sendInSms(
                        '',
                        $value['materiel_name'],
                        $value['type_name'],
                        $value['storage_id'],
                        $value['storage_name'],
                        $datas=['user_id'=>$userId,'main_id' => $mainId],
                        $value['in_storage_num'],
                        $value['in_storage_num']
                    );

                    $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                    $checkBatchNo = StorageBatchModel::where('main_id', $mainId)
                        ->where('batch_no', $batchNo)->first();

                    do {
                        $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                    }
                    while(!empty($checkBatchNo));

                    $batchId = MaterielService::createBatchInfoGetId(
                        $batchNo,
                        $value['id'],
                        $value['cost'],
                        $value['in_storage_num'],
                        0,
                        $mainId
                    );

                    LogInstorageModel::insert([
                        'curr_storage_manage_id' => $value['id'],
                        'materiel_type_id' => $value['materiel_type_id'],//物料id
                        'batch_id' => $batchId,//物料id
                        'materiel_name' => $value['materiel_name'],//物料名称
                        'type_name' => $value['type_name'],//物料型号
                        'materiel_no' => $value['materiel_no'],//物料编号
                        'materiel_class_id' => $value['materiel_class_id'],//物料二级分类主键名称
                        'materiel_class_name' => $value['materiel_class_name'],//物料二级分类名称
                        'materiel_class_no' => $value['materiel_class_no'],//物料二级分类编号
                        'type' => 0,//入库日志类型;0:入库;1:调拨入库;2:直接入库;
                        'storage_id' => $value['id'],//仓库主键id
                        'storage_name' => $value['storage_name'],//仓库名
                        'storage_address' => $value['storage_address'],//仓库地址
                        'last_storage_id' => 0,//调拨前所在仓库id
                        'operate_num' => $value['in_storage_num'],//操作数量
                        'last_storage_num' => 0,//操作前库存数
                        'materiel_mean_cost' => empty($storageManageInfo)?0:$storageManageInfo['materiel_mean_cost'],//物料均价
                        'next_storage_num' => $value['in_storage_num'],//操作后库存数
                        'all_id_type' => $data['all_id_type'],//单据类型;0:无;1:报溢;2:退货;3:采购;
                        'in_storage_time' => strtotime($data['in_storage_time']),//入库时间
                        'shelf_id' => $value['id'],
                        'serial_number' => isset($value['serial_number'])?$value['serial_number']:'',
                        'location_id' => $value['id'],
                        'all_id' => $data['all_id'],//单据id
                        'user_id' => $userId,//操作人用户id
                        'main_id' => $mainId,//主账号id
                        'remark' => empty($data['remark'])?'':$data['remark'],
                        'created_at' => time(),
                    ]);
                }
            }

            if(!empty($arr)) {
                foreach($arr as $v) {
                    MessageService::sendInSms(
                        '',
                        $v['materiel_name'],
                        $v['type_name'],
                        $v['storage_id'],
                        $v['storage_name'],
                        $datas=['user_id'=>$userId,'main_id' => $mainId],
                        $v['in_storage_num'],
                        $v['in_storage_num']
                    );

                    $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                    $checkBatchNo = StorageBatchModel::where('main_id', $mainId)
                        ->where('batch_no', $batchNo)->first();

                    do {
                        $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                    }
                    while(!empty($checkBatchNo));

                    $insertId = StorageManageModel::insertGetId([
                        'materiel_class_id' => $v['materiel_class_id'],
                        'materiel_class_name' => $v['materiel_class_name'],
                        'materiel_class_no' => $v['materiel_class_no'],
                        'type_id' => $v['type_id'],
                        'materiel_name' => $v['materiel_name'],
                        'type_name' => $v['type_name'],
                        'materiel_no' => $v['materiel_no'],
                        'storage_id' => $v['storage_id'],
                        'storage_name' => $v['storage_name'],
                        'storage_address' => $v['storage_address'],
                        'in_storage_num' => $v['in_storage_num'],
                        'virtual_storage_num' => $v['in_storage_num'],
                        'shelf_id' => $v['id'],
                        'location_id' => $v['id'],
                        'main_id' => $mainId,
                        'in_storage_time' => time()
                    ]);

                    $batchId = MaterielService::createBatchInfoGetId(
                        $batchNo,
                        $insertId,
                        0,
                        $v['in_storage_num'],
                        0,
                        $mainId
                    );

                    //生成入库操作记录
                    LogInstorageModel::insert([
                        'curr_storage_manage_id' => $insertId,
                        'materiel_type_id' => $v['type_id'],//物料id
                        'batch_id' => $batchId,//物料id
                        'materiel_name' => $v['materiel_name'],//物料名称
                        'type_name' => $v['type_name'],//物料型号
                        'materiel_no' => $v['materiel_no'],//物料编号
                        'materiel_class_id' => $v['materiel_class_id'],//物料二级分类主键名称
                        'materiel_class_name' => $v['materiel_class_name'],//物料二级分类名称
                        'materiel_class_no' => $v['materiel_class_no'],//物料二级分类编号
                        'type' => 0,//入库日志类型;0:入库;1:调拨入库;2:直接入库;
                        'storage_id' => $v['storage_id'],//仓库主键id
                        'storage_name' => $v['storage_name'],//仓库名
                        'storage_address' => $v['storage_address'],//仓库地址
                        'last_storage_id' => 0,//调拨前所在仓库id
                        'operate_num' => $v['in_storage_num'],//操作数量
                        'last_storage_num' => 0,//操作前库存数
                        'materiel_mean_cost' => 0,//物料均价
                        'next_storage_num' => $v['in_storage_num'],//操作后库存数
                        'all_id_type' => $data['all_id_type'],//单据类型;0:无;1:报溢;2:退货;3:采购;
                        'in_storage_time' => strtotime($data['in_storage_time']),//入库时间
                        'serial_number' => isset($v['serial_number'])?$v['serial_number']:'',
                        'shelf_id' => $v['id'],
                        'location_id' => $v['id'],
                        'all_id' => $data['all_id'],//单据id
                        'user_id' => $userId,//操作人用户id
                        'main_id' => $mainId,//主账号id
                        'remark' => empty($data['remark'])?'':$data['remark'],
                        'created_at' => time(),
                    ]);
                }
            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollback();
            Log::debug('非采购入库：'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '采购入库失败！', 'data' => ''];
        }
    }

    //批次列表
    static public function batchList($id)
    {
        return StorageManageModel::select(
            'a.id',
            'a.type_id',
            'b.type_name',
            'b.materiel_name',
            'b.materiel_no'
        )
            ->from('storage_manage as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
            ->with('batchList', function ($query) {
                $query->select(
                    'storage_batch.id',
                    'storage_batch.id',
                    'batch_no',
                    'storage_manage_id',
                    'batch_num',
                    'batch_left_num',
                    'batch_cost',
                    'purchase_no'
                )
                    ->leftJoin('materiel as b', 'b.id', '=', 'storage_batch.materiel_id');
            })
            ->where('a.id', $id)
            ->first();
    }

    static public function batchMaterielInfo($id)
    {
        return StorageBatchModel::select(
            'a.batch_no',
            'a.batch_num',
            'a.batch_left_num',
            'c.materiel_name',
            'c.type_name',
            'c.materiel_no',
            'd.final_money',
            'd.supplier_name',
            'e.storage_name'
        )
            ->from('storage_batch as a')
            ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
            ->leftJoin('materiel_type as c', 'c.id', '=', 'b.type_id')
            ->leftJoin('materiel as d', 'd.id', 'a.materiel_id')
            ->leftJoin('storage as e', 'e.id', '=', 'b.storage_id')
            ->where('a.id', $id)
            ->first();
    }

    //识别条码
    static public function readBatchNo($data)
    {
        $subBatchInfo = substr($data['batch_no'], -1, 1);

        if($subBatchInfo == 'a') {
            $result = self::readSellPackage($data['batch_no']);

            if(empty($result)) {
                return ['code' => 1, 'msg' => '暂无条码信息', 'data' => ''];
            }
            $result['type'] = 1;
        }
        else {
            $result = self::readMateriel($data['batch_no']);
            if(empty($result)) {
                return ['code' => 1, 'msg' => '暂无条码信息', 'data' => ''];
            }
            $result['type'] = 0;
        }

        return ['code' => 0, 'msg' => 'success', 'data' => $result];
    }

    static private function readSellPackage($batchNo)
    {
        return SellPackageDetailModel::select(
            'a.id',
            'package_no',
            'package_id',
            'package_name',
            'num',
            'price'
        )
            ->from('sell_package_detail as a')
            ->leftJoin('package as b', 'b.id', '=', 'a.package_id')
            ->with('packageContent', function($query) {
                $query->select(
                    'b.in_storage_num',
                    'sell_package_content.materiel_type_id',
                    'a.materiel_name',
                    'a.type_name',
                    'a.materiel_no',
                    'c.id as storage_id',
                    'c.storage_name',
                    'sell_package_content.package_detail_id',
                    'sell_package_content.storage_manage_id',
                    'sell_package_content.num',
                    'sell_package_content.total_num'
                )
                    ->leftJoin('materiel_type as a', 'a.id', '=', 'sell_package_content.materiel_type_id')
                    ->leftJoin('storage_manage as b', 'b.id', '=', 'sell_package_content.storage_manage_id')
                    ->leftJoin('storage as c', 'c.id', '=', 'sell_package_content.storage_id');
            })
            ->where('package_no', $batchNo)
            ->first();
    }

    //商品批次信息
    static private function readMateriel($batchNo)
    {
        return StorageBatchModel::select(
            'a.id as batch_id',
            'batch_no',
            'batch_num',
            'batch_left_num',
            'b.in_storage_num',
            'b.type_id',
            'c.materiel_name',
            'c.type_name',
            'c.materiel_img',
            'c.materiel_no',
            'd.id as storage_id',
            'd.storage_name',
            'a.storage_manage_id',
            'f.price as sell_price'
        )
            ->from('storage_batch as a')
            ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
            ->leftJoin('materiel_type as c', 'b.type_id', '=', 'c.id')
            ->leftJoin('storage as d', 'd.id', '=', 'b.storage_id')
            ->leftJoin('sell_goods_detail_batch as e', 'e.storage_batch_id', '=', 'a.id')
            ->leftJoin('sell_goods_detail as f', 'f.id', '=', 'e.sell_goods_detail_id')
            ->where('batch_no', $batchNo)
            ->first();
    }

    //商品库存批次列表
    static public function materielBatchList($typeId, $sellId, $type, $data)
    {
        $result = StorageManageModel::materielBatchList($typeId, $data);
//        if($type == 0) {
//            $sellGoodsBatchInfo = SellGoodsDetailModel::getBatchInfo($sellId);
//
//            if(empty($sellGoodsBatchInfo)) {
//                foreach($result as &$value) {
//                    $value['is_used'] = 0;
//                }
//            }
//            else {
//                foreach($result as &$value) {
//                    foreach($sellGoodsBatchInfo as $val) {
//                        if($value['materiel_type_id'] == $val['materiel_type_id']) {
//                            $value['is_used'] = 1;
//                        }
//                        else {
//                            $value['is_used'] = 0;
//                        }
//                    }
//                }
//            }
//        }
//        else {
//            $sellPackageBatchInfo = SellPackageContentModel::getBatchInfo($sellId, $data);
//
//            if(empty($sellPackageBatchInfo)) {
//                foreach($result as &$value) {
//                    $value['is_used'] = 0;
//                }
//            }
//            else {
//                foreach($result as &$value) {
//                    foreach($sellPackageBatchInfo as $val) {
//                        if($value['materiel_type_id'] == $val['materiel_type_id']) {
//                            $value['is_used'] = 1;
//                        }
//                        else {
//                            $value['is_used'] = 0;
//                        }
//                    }
//                }
//            }
//        }

        return $result;
    }

    static public function fastOutStorage($data, $formType)
    {
        $batchSign = substr($data['batch_no'], 0, strlen($data['batch_title']));
        $batchNoTag = substr($data['batch_no'], -1, 1);
        $condition=[];
        $pCondition=[];
        switch ($data['code_type']){
            case 0://商品ID
                $condition['id'] = substr($data['batch_no'],5,strlen($data['batch_no'])-1);
                break;
            case 1://序列号
                $condition['id'] = $data['goods_id'];
                break;
            case 2://批次号
                break;
            case 3://条形码
                $condition['bar_code'] =$data['batch_no'];
                break;
        }
            $info = MaterielTypeModel::where($condition)
                ->where(['main_id' => $data['main_id'], 'delete_flag' => 0])->first();

            if (!empty($info)) {
                if ($info['is_product_materiel'] == 1) {//是套餐
                    $pCondition = ['product_id' => $info['id']];
                    if (!empty($info['is_use_serial'])) {
                        return ['code' => 1, 'msg' => '套餐商品已开启序列号，请使用快速出库操作', 'data' => ''];
                    }
                } else {//套餐里的商品
                    $pInfo = MaterielProductContentModel::where([
                        'type_id' => $info['id'],
                        'delete_flag' => 0
                        ])->first();

                    if (!empty($pInfo['product_id'])) {
                        $pCondition = ['product_id' => $pInfo['product_id']];
                    }
                }
                if (!empty($pCondition['product_id'])) {
                    $pList = MaterielProductContentModel::where($pCondition)->where('delete_flag', 0)->get();
                    if (!empty($pList)) {
                        foreach ($pList as $pVal) {
                            $pInfo = MaterielTypeModel::where(['id' => $pVal['type_id']])
                                ->where(['main_id' => $data['main_id'], 'delete_flag' => 0])->first();
                            if (!empty($pInfo['is_use_serial'])) {
                                return ['code' => 1, 'msg' => '套餐商品已开启序列号，请使用快速出库操作', 'data' => ''];
                            }
                        }
                    }
                }
            } else {
                $result = ['code' => 1, 'msg' => '商品信息，不存在!', 'data' => ''];
            }
        //仓库信息
        $storageInfo = StorageModel::where([
                    'id' => $data['storage_id'],
                    'main_id' => $data['main_id'],
                    'delete_flag' => 0,
                    ])->first();

        if(empty($storageInfo)) {
            return ['code'=>1,'msg'=>'您选择的仓库，不存在！','data'=>''];
        }
        if($data['code_type']==0 && strpos($data['batch_no'], 'smycg')!==false){//物料商品id
            $data['batch_no'] = substr($data['batch_no'],5,strlen($data['batch_no'])-1);

            $result = self::goodsOut($data, $formType);
        }elseif($data['code_type']==2 && $batchSign.'0' == $data['batch_title'].$batchNoTag) {//商品批次號
            $result = ['code'=>1,'msg'=>'批次号出库，正在维护中！','data'=>''];
            //$result = self::materielOut($data, $formType);
        } elseif($batchSign.'a' == $data['batch_title'].$batchNoTag) {//套餐批次號

            $result = self::packageFastOut($data);
        }elseif($data['code_type']==1){//序列号
            $result =[];
            if(!empty($data['goods_id']) && !empty($data['batch_no'])){
                $result = self::serialMaterielOut($data,$formType);
            }else{
                $result = ['code'=>1,'msg'=>'序列号商品信息，不存在。','data'=>''];
            }
        }elseif($data['code_type'] == 3){//条形码
            $result =[];

            if(!empty($data['batch_no'])){
                $result = self::barCodeMaterielOut($data,$formType);
            }else{
                $result = ['code'=>1,'msg'=>'条形码商品信息，不存在。','data'=>''];
            }
        }
        CommonService::operateResult($data['user_id'],$result,$data['time']);
        return $result;
    }

    static public function materielOut($data, $formType)
    {
        if(empty($data['sell_id'])) {
            $result = self::materielDirectlyFastOut($data);
        }
        else {
            switch($formType) {
                case 0:
                    $result = self::materielSellFastOut($data);
                    break;
                case 1:
                    break;
                case 2:
                    break;
            }
        }

        return $result;
    }

    static public function goodsOut($data, $formType)
    {
        if(empty($data['sell_id'])) {
            $result = self::goodsDirectlyFastOut($data);
        }else{
            switch($formType) {
                case 0:
                    $result = self::goodsSellFastOut($data);
                    break;
                case 1:
                    break;
                case 2:
                    break;
            }
        }

        return $result;
    }

    /**
     * 序列号识别物料出库
     */
    static public function serialMaterielOut($data, $formType)
    {
        if(empty($data['sell_id'])) {

            $result = self::serialMaterielDirectlyFastOut($data);
        } else {

            switch($formType) {
                case 0:
                    $result = self::serialMaterielSellFastOut($data);
                    break;
                case 1:
                    break;
                case 2:
                    break;
            }
        }

        return $result;
    }

    static public function barCodeMaterielOut($data, $formType)
    {
        if(empty($data['sell_id'])) {
            $result = self::goodsBarCodeFastOut($data);
        }else{
            switch($formType) {
                case 0:
                    $result = self::sellGoodsBarCodeFastOut($data);
                    break;
                case 1:
                    break;
                case 2:
                    break;
            }
        }

        return $result;
    }

    static public function fastOutStorage1($data, $formType)
    {
        if(isset($data['sell_id'])) {
            $sellInfo = SellModel::where('id', $data['sell_id'])->first();
            if($sellInfo['repeal_status']) {
                return [
                    'code' => 1,
                    'msg' => '目标销售单已撤销',
                    'data' => ''
                ];
            }

            if($sellInfo['delete_flag']) {
                return [
                    'code' => 1,
                    'msg' => '目标销售单已删除',
                    'data' => ''
                ];
            }

            if($sellInfo['out_status'] == 2) {
                return [
                    'code' => 1,
                    'msg' => 'success',
                    'data' => [
                        'is_finished' => 1
                    ]
                ];
            }
        }

        $batchSign = substr($data['batch_no'], 0, strlen($data['batch_title']));
        $batchNoTag = substr($data['batch_no'], -1, 1);

        if($batchSign.'0' == $data['batch_title'].$batchNoTag) {//商品批次號
            $result = self::materielFastOut($data);
        }
        else if($batchSign.'a' == $data['batch_title'].$batchNoTag) {//套餐批次號
            $result = self::packageFastOut($data);
        }
        else {//序列號
            $result = self::serialFastOut($data);
        }

        DB::beginTransaction();

        try {
            switch($formType) {
                case 0:
                    self::updateSellStatus($data);
                    break;
            }

            DB::commit();
            return $result;
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('快速出库，出库状态异常'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '快速出库异常', 'data' => ''];
        }
    }

    static private function updateSellStatus()
    {
        if(isset($data['sell_id'])) {
            //更新销售入库状态
            SellModel::where('id',$data['sell_id'])->update(['out_status'=>1, 'prepare_out_status' => 0]);

            $sellGoodsInfo = SellGoodsDetailModel::where('sell_id', $data['sell_id'])
                ->whereRaw('num > out_num')
                ->first();

            $sellPackageInfo = SellPackageDetailModel::where('sell_id', $data['sell_id'])
                ->whereRaw('num > out_num')
                ->first();

            if(empty($sellGoodsInfo) && empty($sellPackageInfo)) {
                SellModel::where('id',$data['sell_id'])->update(['out_status'=>2,'prepare_out_status' => 0]);//全部完成更新状态
                CheckModel::where(['main_id'=>$data['main_id'],'type'=>2,'all_id'=>$data['sell_id']])
                    ->update(['status'=>1,'out_in_status'=>0]);
            }
            else {
                CheckModel::where(['main_id'=>$data['main_id'],'type'=>2,'all_id'=>$data['sell_id']])
                    ->update(['out_in_status'=>1]);
            }
        }
    }

    static private function packageFastOut($data)
    {
        DB::beginTransaction();
        try {
            $sellPackageBatchInfo = SellPackageDetailModel::select(
                'a.id',
                'a.package_id',
                'c.package_name',
                'out_num',
                'a.num'
            )
                ->from('sell_package_detail as a')
                ->leftJoin('package as c', 'c.id', '=', 'a.package_id')
                ->where('a.sell_id', $data['sell_id'])
                ->where('package_no', $data['batch_no'])
                ->first();

            if(empty($sellPackageBatchInfo)) {
                return [
                    'code' => 1,
                    'msg' => '套餐批次不存在，请重试',
                    'data' => ''
                ];
            }

            if($sellPackageBatchInfo['num'] == $sellPackageBatchInfo['out_num']) {
                return ['code' => 1, 'msg' => '该套餐已全部出库', 'data' => ''];
            }

            $logPackageBasicInfo = [
                'package_id' => $sellPackageBatchInfo['package_id'],
                'package_name' => $sellPackageBatchInfo['package_name'],
                'num' => 1,
                'all_id_type' => 2,
                'all_id' => $data['sell_id'],
                'user_id' => $data['user_id'],
                'main_id' => $data['main_id'],
                'created_at' => time()
            ];

            $logId = LogPackageModel::insertGetId($logPackageBasicInfo);

            if(($sellPackageBatchInfo['num'] - $sellPackageBatchInfo['out_num']) < 1) {
                return [
                    'code' => 1,
                    'msg' => '可出库套餐数不足',
                    'data' => ''
                ];
            }

            if($data['out_way']) {

                //获取销售单套餐内容
                $sellPackageContent = SellPackageContentModel::select(
                    'a.id',
                    'num'
                )
                    ->from('sell_package_content as a')
                    ->with('packageBatchInfo', function($query) {
                        $query->select(
                            'a.id',
                            'sell_package_batch.storage_manage_id',
                            'sell_package_content_id',
                            'num',
                            'b.storage_id',
                            'c.storage_name',
                            'c.storage_address',
                            'b.type_id',
                            'd.materiel_name',
                            'd.type_name',
                            'd.materiel_no',
                            'in_storage_num',
                            'materiel_mean_cost',
                            'e.id as materiel_class_id',
                            'e.class_name',
                            'e.class_no',
                            'alert_num',
                            'in_storage_num',
                            'batch_left_num'
                        )
                            ->leftJoin('storage_batch as a', 'sell_package_batch.storage_batch_id', '=', 'a.id')
                            ->leftJoin('storage_manage as b', 'sell_package_batch.storage_manage_id', '=', 'b.id')
                            ->leftJoin('storage as c', 'c.id', '=', 'b.storage_id')
                            ->leftJoin('materiel_type as d', 'd.id', '=', 'b.type_id')
                            ->leftJoin('materiel_class as e', 'e.id', '=', 'd.materiel_class_id');
                    })
                    ->where('package_detail_id', $sellPackageBatchInfo['id'])
                    ->get()->toArray();

                $arr = [];
                $logPackageContentData = [];
                foreach($sellPackageContent as $value) {
                    $totalNum = 0;
                    foreach($value['package_batch_info'] as $val) {
                        $totalNum += $val['batch_left_num'];
                        MessageService::sendAlertSms(
                            $val['materiel_name'],
                            $val['type_name'],
                            $val['in_storage_num'] - $value['num'],
                            $val['alert_num'],
                            $data,
                            $val['storage_id'],
                            $val['storage_name'],
                            $value['num']
                        );

                        MessageService::sendShortSms(
                            $val['materiel_name'],
                            $val['type_name'],
                            $val['in_storage_num'] - $value['num'],
                            $data,
                            $val['storage_id'],
                            $val['storage_name']
                        );

                        MessageService::sendOutSms(
                            $val['materiel_name'],
                            $val['type_name'],
                            $val['in_storage_num'] - $value['num'],
                            $val['storage_name'],
                            $value['num'],
                            $data,
                            $val['storage_id'],
                            $val['alert_num']
                        );

                        $logPackageContentData[] = [
                            'log_package_id' => $logId,
                            'package_id' => $sellPackageBatchInfo['package_id'],
                            'storage_id' => $val['storage_id'],
                            'storage_name' => $val['storage_name'],
                            'storage_address' => $val['storage_address'],
                            'materiel_class_id' => $val['materiel_class_id'],
                            'materiel_class_name' => $val['class_name'],
                            'materiel_class_no' => $val['class_name'],
                            'materiel_type_id' => $val['type_id'],
                            'materiel_name' => $val['materiel_name'],
                            'type_name' => $val['type_name'],
                            'materiel_no' => $val['materiel_no'],
                            'operate_num' => $value['num'],
                            'out_storage_manage_id' => $val['storage_manage_id'],
                            'last_storage_num' => $val['in_storage_num'],
                            'next_storage_num' => $val['in_storage_num'] - $value['num'],
                            'all_id_type' => 4,
                            'all_id' => $data['sell_id'],
                            'user_id' => $data['user_id'],
                            'main_id' => $data['main_id'],
                            'storage_batch_id' => $val['id'],
                            'created_at' => time()
                        ];

                        if($val['in_storage_num'] < $value['num']) {
                            return [
                                'code' => 1,
                                'msg' => '库存不足，无法出库',
                                'data' => ''
                            ];
                        }

                        StorageManageModel::where('id', $val['storage_manage_id'])
                            ->update([
                                'in_storage_num' => DB::raw("in_storage_num -".$value['num']),
                                'virtual_storage_num' => DB::raw("virtual_storage_num -".$value['num'])
                            ]);

                        StorageBatchModel::where('id', $val['id'])
                            ->decrement('batch_left_num', $value['num']);
                    }

                    if($totalNum < $value['num']) {
                        return [
                            'code' => 1,
                            'msg' => '批次库存数量不足，无法出库',
                            'data' => ''
                        ];
                    }
                }
                LogPackageContentModel::insert($logPackageContentData);
            }
            else {
                //获取销售单套餐内容
                $sellPackageContent = SellPackageContentModel::select(
                    'a.id',
                    'storage_manage_id',
                    'num',
                    'b.storage_id',
                    'c.storage_name',
                    'c.storage_address',
                    'b.type_id',
                    'd.materiel_name',
                    'd.type_name',
                    'd.materiel_no',
                    'in_storage_num',
                    'materiel_mean_cost',
                    'e.id as materiel_class_id',
                    'e.class_name',
                    'e.class_no',
                    'alert_num'
                )
                    ->from('sell_package_content as a')
                    ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                    ->leftJoin('storage as c', 'c.id', '=', 'b.storage_id')
                    ->leftJoin('materiel_type as d', 'd.id', '=', 'b.type_id')
                    ->leftJoin('materiel_class as e', 'e.id', '=', 'd.materiel_class_id')
                    ->where('package_detail_id', $sellPackageBatchInfo['id'])
                    ->get()->toArray();

                $arr = [];
                $logPackageContentData = [];
                foreach($sellPackageContent as $value) {
                    if($value['num'] > $value['in_storage_num']) {
                        return [
                            'code' => 1,
                            'msg' => '库存数不足，无法完成出库',
                            'data' => ''
                        ];
                    }

                    $arr[] = [
                        'storage_manage_id' => $value['storage_manage_id'],
                        'operate_num' => $value['num'],
                        'in_storage_num' => $value['in_storage_num'],
                        'alert_num' => $value['in_storage_num'],
                        'storage_id' => $value['storage_id'],
                        'storage_name' => $value['storage_name'],
                        'storage_address' => $value['storage_address'],
                        'materiel_name' => $value['materiel_name'],
                        'type_name' => $value['type_name'],
                    ];

                    $logPackageContentData[] = [
                        'log_package_id' => $logId,
                        'package_id' => $sellPackageBatchInfo['package_id'],
                        'storage_id' => $value['storage_id'],
                        'storage_name' => $value['storage_name'],
                        'storage_address' => $value['storage_address'],
                        'materiel_class_id' => $value['materiel_class_id'],
                        'materiel_class_name' => $value['class_name'],
                        'materiel_class_no' => $value['class_name'],
                        'materiel_type_id' => $value['type_id'],
                        'materiel_name' => $value['materiel_name'],
                        'type_name' => $value['type_name'],
                        'materiel_no' => $value['materiel_no'],
                        'operate_num' => $value['num'],
                        'out_storage_manage_id' => $value['storage_manage_id'],
                        'last_storage_num' => $value['in_storage_num'],
                        'next_storage_num' => $value['in_storage_num'] - $value['num'],
                        'all_id_type' => 4,
                        'all_id' => $data['sell_id'],
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'created_at' => time()
                    ];
                }

                LogPackageContentModel::insert($logPackageContentData);

                foreach($arr as $v) {
                    MessageService::sendAlertSms(
                        $v['materiel_name'],
                        $v['type_name'],
                        $v['in_storage_num'] - $v['operate_num'],
                        $v['alert_num'],
                        $data,
                        $v['storage_id'],
                        $v['storage_name'],
                        $v['operate_num']
                    );

                    MessageService::sendShortSms(
                        $v['materiel_name'],
                        $v['type_name'],
                        $v['in_storage_num'] - $v['operate_num'],
                        $data,
                        $v['storage_id'],
                        $v['storage_name']
                    );

                    MessageService::sendOutSms(
                        $v['materiel_name'],
                        $v['type_name'],
                        $v['in_storage_num'] - $v['operate_num'],
                        $v['storage_name'],
                        $v['operate_num'],
                        $data,
                        $v['storage_id'],
                        $v['alert_num']
                    );

                    StorageManageModel::where('id', $v['storage_manage_id'])
                        ->update([
                            'in_storage_num' => DB::raw("in_storage_num -".$v['operate_num']),
                            'virtual_storage_num' => DB::raw("virtual_storage_num -".$v['operate_num'])
                        ]);
                }
            }

            SellPackageDetailModel::where('id', $sellPackageBatchInfo['id'])
                ->increment('out_num', 1);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('销售单套餐快速出库异常'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '销售单套餐快速出库异常', 'data' => ''];
        }
    }

    static private function materielFastOut($data)
    {
        if(isset($data['sell_id'])) {
            return self::materielSellFastOut($data);
        }
        else {
            return self::materielDirectlyFastOut($data);
        }
    }

    static private function materielDirectlyFastOut($data)
    {
        DB::beginTransaction();

        try {

            $storageBatchInfo = StorageBatchModel::select(
                'b.id as storage_manage_id',
                'b.type_id as materiel_type_id',
                'c.materiel_name',
                'c.type_name',
                'c.materiel_no',
                'd.id as materiel_class_id',
                'd.class_name',
                'd.class_no',
                'e.id as storage_id',
                'e.storage_name',
                'e.storage_address',
                'in_storage_num',
                'materiel_mean_cost',
                'b.virtual_storage_num',
                'b.alert_num'
            )
                ->from('storage_batch as a')
                ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                ->leftJoin('materiel_type as c', 'c.id', '=', 'b.type_id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'c.materiel_class_id')
                ->leftJoin('storage as e', 'e.id', '=', 'b.storage_id')
                ->where('batch_no', $data['batch_no'])->first();

            if(empty($storageBatchInfo)) {

                return ['code' => 1,'msg' => '批次不存在，无法出库','data' => ''];
            }

            if($storageBatchInfo['batch_left_num'] <= 0) {

                return ['code' => 1,'msg' => '库存批次数量不足,无法出库','data' => ''];
            }

            if($storageBatchInfo['in_storage_num'] <= 0) {

                return ['code' => 1,'msg' => '库存数量不足，无法出库','data' => ''];
            }

            if($storageBatchInfo['virtual_storage_num'] <=0) {

                return ['code' => 1,'msg' => '商品虚拟库存数量不足','data' => ''];
            }

            $logOutInfo = [
                'type' => 2,
                'storage_batch_id' => $storageBatchInfo['batch_id'],
                'storage_id' => $storageBatchInfo['storage_id'],
                'storage_name' => $storageBatchInfo['storage_name'],
                'storage_address' => $storageBatchInfo['storage_address'],
                'curr_storage_manage_id' => $storageBatchInfo['storage_manage_id'],
                'materiel_class_id' => $storageBatchInfo['materiel_class_id'],
                'materiel_class_name' => $storageBatchInfo['class_name'],
                'materiel_class_no' => $storageBatchInfo['class_no'],
                'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                'materiel_name' => $storageBatchInfo['materiel_name'],
                'type_name' => $storageBatchInfo['type_name'],
                'materiel_no' => $storageBatchInfo['materiel_no'],
                'operate_num' => 1,
                'last_storage_num' => $storageBatchInfo['in_storage_num'],
                'next_storage_num' => $storageBatchInfo['in_storage_num'] - 1,
                'sell_price' => $storageBatchInfo['materiel_mean_cost'],
                'materiel_mean_cost' => $storageBatchInfo['materiel_mean_cost'],
                'user_id' => $data['user_id'],
                'main_id' => $data['main_id'],
                'out_storage_time' => time(),
                'created_at' => time()
            ];

            MessageService::sendAlertSms(
                $storageBatchInfo['materiel_name'],
                $storageBatchInfo['type_name'],
                $storageBatchInfo['in_storage_num'] - 1,
                $storageBatchInfo['alert_num'],
                $data,
                $storageBatchInfo['storage_id'],
                $storageBatchInfo['storage_name'],
                1
            );

            MessageService::sendShortSms(
                $storageBatchInfo['materiel_name'],
                $storageBatchInfo['type_name'],
                $storageBatchInfo['in_storage_num'] - 1,
                $data,
                $storageBatchInfo['storage_id'],
                $storageBatchInfo['storage_name']
            );

            MessageService::sendOutSms(
                $storageBatchInfo['materiel_name'],
                $storageBatchInfo['type_name'],
                $storageBatchInfo['in_storage_num'] - 1,
                $storageBatchInfo['storage_name'],
                1,
                $data,
                $storageBatchInfo['storage_id'],
                $storageBatchInfo['alert_num']
            );

            LogOutStorageModel::insert($logOutInfo);

            StorageBatchModel::where('id', $storageBatchInfo['batch_id'])
                ->decrement('batch_left_num', 1);

            StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw("in_storage_num - 1"),
                    'virtual_storage_num' => DB::raw("virtual_storage_num - 1")
                ]);

            /* SellGoodsDetailModel::where('id',$storageBatchInfo['sell_goods_detail_id'])
                ->increment('out_num', 1); */

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('商品直接出库异常'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '商品直接出库异常，请重试', 'data' => ''];
        }
    }

    static private function goodsDirectlyFastOut($data){
        DB::beginTransaction();
        try {
            $storageBatchInfo = materielTypeModel::select(
                'b.id as storage_manage_id',
                'b.type_id as materiel_type_id',
                'a.materiel_name',
                'a.type_name',
                'a.materiel_no',
                'd.id as materiel_class_id',
                'd.class_name',
                'd.class_no',
                'e.id as storage_id',
                'e.storage_name',
                'e.storage_address',
                'in_storage_num',
                'materiel_mean_cost',
                'b.virtual_storage_num',
                'b.alert_num',
                'a.is_use_serial',
                'a.selling_price'
                )
                ->from('materiel_type as a')
                ->leftJoin('storage_manage as b', 'b.type_id', '=', 'a.id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'a.materiel_class_id')
                ->leftJoin('storage as e', 'e.id', '=', 'b.storage_id')
                ->where('a.id', $data['batch_no'])
                ->where('a.main_id',$data['main_id'])
                ->where('b.storage_id',$data['storage_id'])
                ->where('a.delete_flag',0)
                ->where('b.delete_flag',0)
                ->first();

                if(empty($storageBatchInfo)) {
                    return ['code' => 1, 'msg' => '商品信息不存在，无法出库', 'data' => ''];
                }
                if($storageBatchInfo['in_storage_num'] <= 0) {
                    return ['code' => 1, 'msg' => '库存数量不足，无法出库', 'data' => ''];
                }
                if($storageBatchInfo['is_use_serial'] == 1) {
                    return ['code' => 1, 'msg' => '您开启了序列号，请选择序列号出库！', 'data' => ''];
                }
                if($storageBatchInfo['virtual_storage_num'] <=0) {
                    return ['code' => 1,'msg' => '商品虚拟库存数量不足','data' => ''];
                }
                //库存数达到预警
                    $sortFlag = 0;
                if($storageBatchInfo['in_storage_num']-1 <= $storageBatchInfo['alert_num']) {
                    $sortFlag = 1;
                }

                $logOutInfo = [
                    'type' => 4,
                    'storage_batch_id' => "",
                    'storage_id' => $storageBatchInfo['storage_id'],
                    'storage_name' => $storageBatchInfo['storage_name'],
                    'storage_address' => $storageBatchInfo['storage_address'],
                    'curr_storage_manage_id' => $storageBatchInfo['storage_manage_id'],
                    'materiel_class_id' => $storageBatchInfo['materiel_class_id'],
                    'materiel_class_name' => $storageBatchInfo['class_name'],
                    'materiel_class_no' => $storageBatchInfo['class_no'],
                    'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                    'materiel_name' => $storageBatchInfo['materiel_name'],
                    'type_name' => $storageBatchInfo['type_name'],
                    'materiel_no' => $storageBatchInfo['materiel_no'],
                    'operate_num' => 1,
                    'last_storage_num' => $storageBatchInfo['in_storage_num'],
                    'next_storage_num' => $storageBatchInfo['in_storage_num'] - 1,
                    'sell_price' => $storageBatchInfo['materiel_mean_cost'],
                    'materiel_mean_cost' => $storageBatchInfo['materiel_mean_cost'],
                    'user_id' => $data['user_id'],
                    'main_id' => $data['main_id'],
                    'out_storage_time' => $data['time'],
                    'created_at' => $data['time']
                ];

                MessageService::sendAlertSms(
                    $storageBatchInfo['materiel_name'],
                    $storageBatchInfo['type_name'],
                    $storageBatchInfo['in_storage_num'] - 1,
                    $storageBatchInfo['alert_num'],
                    $data,
                    $storageBatchInfo['storage_id'],
                    $storageBatchInfo['storage_name'],
                    1
                    );

                MessageService::sendShortSms(
                    $storageBatchInfo['materiel_name'],
                    $storageBatchInfo['type_name'],
                    $storageBatchInfo['in_storage_num'] - 1,
                    $data,
                    $storageBatchInfo['storage_id'],
                    $storageBatchInfo['storage_name']
                    );

                MessageService::sendOutSms(
                    $storageBatchInfo['materiel_name'],
                    $storageBatchInfo['type_name'],
                    $storageBatchInfo['in_storage_num'] - 1,
                    $storageBatchInfo['storage_name'],
                    1,
                    $data,
                    $storageBatchInfo['storage_id'],
                    $storageBatchInfo['alert_num']
                );

                LogOutStorageModel::insert($logOutInfo);

                StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw("in_storage_num - 1"),
                    'virtual_storage_num' => DB::raw("virtual_storage_num - 1"),
                    'sort_flag'=>$sortFlag
                ]);

                MaterielTypeModel::where(['id' => $storageBatchInfo['materiel_type_id']])->update(['price_last' => $storageBatchInfo['selling_price']]);
                DB::commit();
                return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('商品ID扫码出库异常'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '商品ID扫码,出库失败！', 'data' => ''];
        }

    }

    static private function goodsBarCodeFastOut($data){

        DB::beginTransaction();

        try {
            $storageBatchInfo = materielTypeModel::select(
                'b.id as storage_manage_id',
                'b.type_id as materiel_type_id',
                'a.materiel_name',
                'a.type_name',
                'a.materiel_no',
                'd.id as materiel_class_id',
                'd.class_name',
                'd.class_no',
                'e.id as storage_id',
                'e.storage_name',
                'e.storage_address',
                'in_storage_num',
                'materiel_mean_cost',
                'b.virtual_storage_num',
                'b.alert_num',
                'a.is_use_serial',
                'a.selling_price'
                )
                ->from('materiel_type as a')
                ->leftJoin('storage_manage as b', 'b.type_id', '=', 'a.id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'a.materiel_class_id')
                ->leftJoin('storage as e', 'e.id', '=', 'b.storage_id')
                ->where('a.bar_code', $data['batch_no'])
                ->where('a.main_id',$data['main_id'])
                ->where('b.storage_id',$data['storage_id'])
                ->where('a.delete_flag',0)
                ->where('b.delete_flag',0)
                ->first();

                if(empty($storageBatchInfo)) {
                    return ['code' => 1,'msg' => '条形码不存在，无法出库','data' => ''];
                }

                if($storageBatchInfo['is_use_serial'] == 1) {

                    return ['code' => 1,'msg' => '库存数量不足，无法出库','data' => ''];
                }

                if($storageBatchInfo['in_storage_num'] <= 0) {
                    return ['code' => 1,'msg' => '库存数量不足，无法出库','data' => ''];
                }

                if($storageBatchInfo['virtual_storage_num'] <=0) {
                    return ['code' => 1,'msg' => '商品虚拟库存数量不足','data' => ''];
                }
                //库存数达到预警
                $sortFlag = 0;
                if($storageBatchInfo['in_storage_num']-1 <= $storageBatchInfo['alert_num']) {
                    $sortFlag = 1;
                }
                $logOutInfo = [
                    'type' => 4,
                    'storage_batch_id' => "",
                    'storage_id' => $storageBatchInfo['storage_id'],
                    'storage_name' => $storageBatchInfo['storage_name'],
                    'storage_address' => $storageBatchInfo['storage_address'],
                    'curr_storage_manage_id' => $storageBatchInfo['storage_manage_id'],
                    'materiel_class_id' => $storageBatchInfo['materiel_class_id'],
                    'materiel_class_name' => $storageBatchInfo['class_name'],
                    'materiel_class_no' => $storageBatchInfo['class_no'],
                    'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                    'materiel_name' => $storageBatchInfo['materiel_name'],
                    'type_name' => $storageBatchInfo['type_name'],
                    'materiel_no' => $storageBatchInfo['materiel_no'],
                    'operate_num' => 1,
                    'last_storage_num' => $storageBatchInfo['in_storage_num'],
                    'next_storage_num' => $storageBatchInfo['in_storage_num'] - 1,
                    'sell_price' => $storageBatchInfo['materiel_mean_cost'],
                    'materiel_mean_cost' => $storageBatchInfo['materiel_mean_cost'],
                    'user_id' => $data['user_id'],
                    'main_id' => $data['main_id'],
                    'out_storage_time' => time(),
                    'created_at' => time()
                ];

                MessageService::sendAlertSms(
                    $storageBatchInfo['materiel_name'],
                    $storageBatchInfo['type_name'],
                    $storageBatchInfo['in_storage_num'] - 1,
                    $storageBatchInfo['alert_num'],
                    $data,
                    $storageBatchInfo['storage_id'],
                    $storageBatchInfo['storage_name'],
                    1
                    );

                MessageService::sendShortSms(
                    $storageBatchInfo['materiel_name'],
                    $storageBatchInfo['type_name'],
                    $storageBatchInfo['in_storage_num'] - 1,
                    $data,
                    $storageBatchInfo['storage_id'],
                    $storageBatchInfo['storage_name']
                    );

                MessageService::sendOutSms(
                    $storageBatchInfo['materiel_name'],
                    $storageBatchInfo['type_name'],
                    $storageBatchInfo['in_storage_num'] - 1,
                    $storageBatchInfo['storage_name'],
                    1,
                    $data,
                    $storageBatchInfo['storage_id'],
                    $storageBatchInfo['alert_num']
                    );

                LogOutStorageModel::insert($logOutInfo);

                StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw("in_storage_num - 1"),
                    'virtual_storage_num' => DB::raw("virtual_storage_num - 1"),
                    'sort_flag'=>$sortFlag
                ]);
                MaterielTypeModel::where(['id' => $storageBatchInfo['materiel_type_id']])->update(['price_last' => $storageBatchInfo['selling_price']]);
                DB::commit();
                return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('条形码商品扫码出库异常'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '条形码扫码，出库失败！', 'data' => ''];
        }

    }

    static private function serialMaterielDirectlyFastOut($data)
    {
        DB::beginTransaction();
        try {
            $info = MaterielTypeModel::where(['id'=>$data['goods_id'],'delete_flag'=>0])->first();
            if(empty($info)) {
                return ['code' => 1,'msg' => '序列号商品不存在，无法出库','data' => ''];
            }
            $storageBatchInfo = StorageBatchModel::select(
                'b.id as storage_manage_id',
                'b.type_id as materiel_type_id',
                'c.materiel_name',
                'c.type_name',
                'c.materiel_no',
                'd.id as materiel_class_id',
                'd.class_name',
                'd.class_no',
                'e.id as storage_id',
                'e.storage_name',
                'e.storage_address',
                'in_storage_num',
                'materiel_mean_cost',
                'a.status as serial_status',
                'b.virtual_storage_num',
                'b.alert_num',
                'c.selling_price'
                )
                ->from('serial_number as a')
                ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                ->leftJoin('materiel_type as c', 'c.id', '=', 'b.type_id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'c.materiel_class_id')
                ->leftJoin('storage as e', 'e.id', '=', 'b.storage_id')
                ->where('serial_no', $data['batch_no'])
                ->where('a.goods_id', $data['goods_id'])
                ->where('b.storage_id',$data['storage_id'])
                ->where('b.main_id',$data['main_id'])
                ->where('c.delete_flag',0)
                ->where('b.delete_flag',0)
                ->first();

                if(empty($storageBatchInfo)) {

                    return ['code' => 1,'msg' => '序列号商品不存在，无法出库','data' => ''];
                }

                if($storageBatchInfo['serial_status'] == 0) {

                    return ['code' => 1,'msg' => '序列号已使用,无法出库','data' => ''];
                }

                if($storageBatchInfo['in_storage_num'] <= 0) {

                    return ['code' => 1,'msg' => '库存数量不足，无法出库','data' => ''];
                }
                if($storageBatchInfo['virtual_storage_num'] <= 0) {

                    return ['code' => 1,'msg' => '商品虚拟库存数量不足','data' => ''];
                }
                //库存数达到预警
                $sortFlag = 0;
                if($storageBatchInfo['in_storage_num']-1 <= $storageBatchInfo['alert_num']) {
                    $sortFlag = 1;
                }
                $logOutInfo = [
                    'type' => 4,
                    'storage_id' => $storageBatchInfo['storage_id'],
                    'storage_name' => $storageBatchInfo['storage_name'],
                    'storage_address' => $storageBatchInfo['storage_address'],
                    'curr_storage_manage_id' => $storageBatchInfo['storage_manage_id'],
                    'materiel_class_id' => $storageBatchInfo['materiel_class_id'],
                    'materiel_class_name' => $storageBatchInfo['class_name'],
                    'materiel_class_no' => $storageBatchInfo['class_no'],
                    'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                    'materiel_name' => $storageBatchInfo['materiel_name'],
                    'type_name' => $storageBatchInfo['type_name'],
                    'materiel_no' => $storageBatchInfo['materiel_no'],
                    'operate_num' => 1,
                    'last_storage_num' => $storageBatchInfo['in_storage_num'],
                    'next_storage_num' => $storageBatchInfo['in_storage_num'] - 1,
                    'sell_price' => $storageBatchInfo['materiel_mean_cost'],
                    'materiel_mean_cost' => $storageBatchInfo['materiel_mean_cost'],
                    'user_id' => $data['user_id'],
                    'main_id' => $data['main_id'],
                    'out_storage_time' => $data['time'],
                    'created_at' => $data['time'],
                    'serial_number'=>$data['batch_no']
                ];

                MessageService::sendAlertSms(
                    $storageBatchInfo['materiel_name'],
                    $storageBatchInfo['type_name'],
                    $storageBatchInfo['in_storage_num'] - 1,
                    $storageBatchInfo['alert_num'],
                    $data,
                    $storageBatchInfo['storage_id'],
                    $storageBatchInfo['storage_name'],
                    1
                    );

                MessageService::sendShortSms(
                    $storageBatchInfo['materiel_name'],
                    $storageBatchInfo['type_name'],
                    $storageBatchInfo['in_storage_num'] - 1,
                    $data,
                    $storageBatchInfo['storage_id'],
                    $storageBatchInfo['storage_name']
                    );

                MessageService::sendOutSms(
                    $storageBatchInfo['materiel_name'],
                    $storageBatchInfo['type_name'],
                    $storageBatchInfo['in_storage_num'] - 1,
                    $storageBatchInfo['storage_name'],
                    1,
                    $data,
                    $storageBatchInfo['storage_id'],
                    $storageBatchInfo['alert_num']
                    );

               $id = LogOutStorageModel::insert($logOutInfo);

                $bool = StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw("in_storage_num - 1"),
                    'virtual_storage_num' => DB::raw("virtual_storage_num - 1"),
                    'sort_flag'=>$sortFlag
                ]);

               /*  $bool=SellGoodsDetailModel::where('id',$storageBatchInfo['sell_goods_detail_id'])
                ->increment('out_num', 1); */

                $bool = SerialNumberModel::where([
                    'serial_no' => $data['batch_no'],
                    'goods_id'  => $storageBatchInfo['materiel_type_id'],
                    'storage_manage_id' => $storageBatchInfo['storage_manage_id']
                ])->update(['status'=>0]);
                MaterielTypeModel::where(['id' => $storageBatchInfo['materiel_type_id']])->update(['price_last' => $storageBatchInfo['selling_price']]);
                DB::commit();
                return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('序列号扫码，出库失败'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '序列号扫码,出库失败!', 'data' => ''];
        }
    }

    //销售单快速出库
    static private function materielSellFastOut($data)
    {
        if($data['out_way']) {
            $sellGoodsBatchInfo = SellGoodsDetailModel::select(
                'a.id',
                'b.id as sell_goods_batch_id',
                'a.materiel_type_id',
                'f.materiel_name',
                'f.type_name',
                'f.materiel_no',
                'a.num',
                'a.out_num',
                'b.num as batch_num',
                'b.rest_num',
                'storage_batch_id',
                'batch_left_num',
                'in_storage_num',
                'storage_id',
                'e.storage_name',
                'e.storage_address',
                'd.id as storage_manage_id',
                'f.materiel_class_id',
                'g.class_name',
                'g.class_no',
                'materiel_mean_cost',
                'alert_num',
                'c.id as batch_id',
                'a.price',
                'd.virtual_storage_num'
            )
                ->from('sell_goods_detail as a')
                ->leftJoin('sell_goods_detail_batch as b', 'b.sell_goods_detail_id', '=', 'a.id')
                ->leftJoin('storage_batch as c', 'c.id', '=', 'b.storage_batch_id')
                ->leftJoin('storage_manage as d', 'd.id', '=', 'c.storage_manage_id')
                ->leftJoin('storage as e', 'e.id', '=', 'd.storage_id')
                ->leftJoin('materiel_type as f', 'f.id', '=', 'd.type_id')
                ->leftJoin('materiel_class as g', 'g.id', '=', 'f.materiel_class_id')
                ->where('c.batch_no', $data['batch_no'])
                ->where('a.sell_id', $data['sell_id'])
                ->orderBy('b.rest_num', 'desc')
                ->first();

            //商品已设置批次号
            if(!empty($sellGoodsBatchInfo)) {
                if($sellGoodsBatchInfo['num'] == $sellGoodsBatchInfo['out_num']) {
                    return [
                        'code' => 1,
                        'msg' => '该商品已全部出库，无法重复操作',
                        'data' => ''
                    ];
                }

                if($sellGoodsBatchInfo['batch_left_num'] < 1) {
                    return [
                        'code' => 1,
                        'msg' => '批次库存数量不足',
                        'data' => ''
                    ];
                }

                if($sellGoodsBatchInfo['rest_num'] < 1) {
                    return [
                        'code' => 1,
                        'msg' => '商品所设置的可出库批次数量不足',
                        'data' => ''
                    ];
                }
            }
            else {
                //商品批次号信息
                $sellGoodsBatchInfo = StorageBatchModel::select(
                    'a.*',
                    'type_id',
                    'in_storage_num',
                    'b.type_id as materiel_type_id',
                    'd.materiel_name',
                    'd.type_name',
                    'd.materiel_no',
                    'b.storage_id',
                    'c.storage_name',
                    'c.storage_address',
                    'd.materiel_class_id',
                    'e.class_name',
                    'e.class_no',
                    'materiel_mean_cost',
                    'alert_num',
                    'b.virtual_storage_num'
                )
                    ->from('storage_batch as a')
                    ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                    ->leftJoin('storage as c', 'c.id', '=', 'b.storage_id')
                    ->leftJoin('materiel_type as d', 'd.id', '=', 'b.type_id')
                    ->leftJoin('materiel_class as e', 'e.id', '=', 'd.materiel_class_id')
                    ->where('batch_no', $data['batch_no'])
                    ->first();

                $sellGoodsBatchInfo['price'] = $sellGoodsBatchInfo['materiel_mean_cost'];

                if(empty($sellGoodsBatchInfo)) {
                    return ['code' => 1, 'msg' => '无此批次信息', 'data' => ''];
                }

                //销售单内商品信息
                $sellGoodsInfo = SellGoodsDetail::where([
                    'sell_id' => $data['sell_id'],
                    'materiel_type_id' => $sellGoodsBatchInfo['materiel_type_id']
                ])->first();

                if(empty($sellGoodsInfo)) {
                    return ['code' => 1, 'msg' => '当前批次号不属于该商品', 'data' => ''];
                }
//
                if($sellGoodsInfo['num'] == $sellGoodsInfo['out_num']) {
                    return [
                        'code' => 1,
                        'msg' => '该商品已全部出库，无法重复操作',
                        'data' => ''
                    ];
                }

                if($sellGoodsBatchInfo['batch_left_num'] < 1) {
                    return [
                        'code' => 1,
                        'msg' => '批次库存数量不足',
                        'data' => ''
                    ];
                }

                $sellGoodsBatchInfo['storage_batch_id'] = $sellGoodsBatchInfo['id'];
                $sellGoodsBatchInfo['batch_id'] = $sellGoodsBatchInfo['id'];
                $sellGoodsBatchInfo['id'] = $sellGoodsInfo['id'];
                $sellGoodsBatchInfo['sell_goods_id'] = 0;
            }
        }
        else {
            $sellGoodsBatchInfo = SellGoodsDetailModel::select(
                'a.id',
                'a.materiel_type_id',
                'e.materiel_name',
                'e.type_name',
                'e.materiel_no',
                'c.id as storage_batch_id',
                'batch_left_num',
                'in_storage_num',
                'storage_id',
                'd.storage_name',
                'd.storage_address',
                'b.id as storage_manage_id',
                'e.materiel_class_id',
                'f.class_name',
                'f.class_no',
                'materiel_mean_cost',
                'alert_num',
                'c.id as batch_id',
                'a.num',
                'a.out_num',
                'a.price',
                'b.virtual_storage_num'
            )
                ->from('sell_goods_detail as a')
                ->leftJoin('storage_manage as b', 'a.materiel_type_id', '=', 'b.type_id')
                ->leftJoin('storage_batch as c', 'c.storage_manage_id', '=', 'b.id')
                ->leftJoin('storage as d', 'd.id', '=', 'b.storage_id')
                ->leftJoin('materiel_type as e', 'e.id', '=', 'b.type_id')
                ->leftJoin('materiel_class as f', 'f.id', '=', 'e.materiel_class_id')
                ->where('batch_no', $data['batch_no'])
                ->where('a.sell_id', $data['sell_id'])
                ->orderBy('batch_left_num', 'desc')
                ->first();

            if(empty($sellGoodsBatchInfo)) {
                return [
                    'code' => 1,
                    'msg' => '销售单内无此批次信息',
                    'data' => ''
                ];
            }
        }

        if($sellGoodsBatchInfo['in_storage_num'] <= 0) {
            return [
                'code' => 1,
                'msg' => '商品库存数量不足',
                'data' => ''
            ];
        }
        if($sellGoodsBatchInfo['virtual_storage_num'] <= 0) {
            return ['code' => 1,'msg' => '商品虚拟库存数量不足','data' => ''];
        }
        $logOutInfo = [
            'type' => 4,
            'storage_batch_id' => $sellGoodsBatchInfo['storage_batch_id'],
            'storage_id' => $sellGoodsBatchInfo['storage_id'],
            'storage_name' => $sellGoodsBatchInfo['storage_name'],
            'storage_address' => $sellGoodsBatchInfo['storage_address'],
            'curr_storage_manage_id' => $sellGoodsBatchInfo['storage_manage_id'],
            'materiel_class_id' => $sellGoodsBatchInfo['materiel_class_id'],
            'materiel_class_name' => $sellGoodsBatchInfo['class_name'],
            'materiel_class_no' => $sellGoodsBatchInfo['class_no'],
            'materiel_type_id' => $sellGoodsBatchInfo['materiel_type_id'],
            'materiel_name' => $sellGoodsBatchInfo['materiel_name'],
            'type_name' => $sellGoodsBatchInfo['type_name'],
            'materiel_no' => $sellGoodsBatchInfo['materiel_no'],
            'operate_num' => 1,
            'last_storage_num' => $sellGoodsBatchInfo['in_storage_num'],
            'next_storage_num' => $sellGoodsBatchInfo['in_storage_num'] - 1,
            'sell_price' => $sellGoodsBatchInfo['price'],
            'materiel_mean_cost' => $sellGoodsBatchInfo['materiel_mean_cost'],
            'all_id_type' => 2,
            'all_id' => $data['sell_id'],
            'user_id' => $data['user_id'],
            'main_id' => $data['main_id'],
            'out_storage_time' => time(),
            'fact_out_time' => time(),
            'created_at' => time()
        ];

        MessageService::sendAlertSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $sellGoodsBatchInfo['alert_num'],
            $data,
            $sellGoodsBatchInfo['storage_id'],
            $sellGoodsBatchInfo['storage_name'],
            1
       );

        MessageService::sendShortSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $data,
           $sellGoodsBatchInfo['storage_id'],
            $sellGoodsBatchInfo['storage_name'],
        );

       MessageService::sendOutSms(
           $sellGoodsBatchInfo['materiel_name'],
           $sellGoodsBatchInfo['type_name'],
           $sellGoodsBatchInfo['in_storage_num'] - 1,
            $sellGoodsBatchInfo['storage_name'],
           1,
            $data,
            $sellGoodsBatchInfo['storage_id'],
           $sellGoodsBatchInfo['alert_num'],
       );

        DB::beginTransaction();

        try {
            SellGoodsDetailModel::where('id', $sellGoodsBatchInfo['id'])
                ->increment('out_num', 1);

            SellGoodsDetailBatchModel::where('id', $sellGoodsBatchInfo['sell_goods_id'])
                ->decrement('rest_num', 1);

            StorageManageModel::where('id', $sellGoodsBatchInfo['storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw("in_storage_num - 1"),
                    'virtual_storage_num' => DB::raw("virtual_storage_num - 1")
                ]);

            StorageBatchModel::where('id', $sellGoodsBatchInfo['batch_id'])
                ->decrement('batch_left_num', 1);

            LogOutStorageModel::insert($logOutInfo);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('快速出库异常'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '快速出库异常', 'data' => ''];
        }
    }

    //商品ID识别-销售单快速出库
    static private function goodsSellFastOut($data)
    {
        $sellGoodsBatchInfo = SellGoodsDetailModel::select(
                'a.id',
                'a.materiel_type_id',
                'e.materiel_name',
                'e.type_name',
                'e.materiel_no',
                'in_storage_num',
                'storage_id',
                'd.storage_name',
                'd.storage_address',
                'b.id as storage_manage_id',
                'e.materiel_class_id',
                'f.class_name',
                'f.class_no',
                'materiel_mean_cost',
                'alert_num',
                'a.num',
                'a.out_num',
                'a.price',
                'b.virtual_storage_num',
                'a.price'
                )
                ->from('sell_goods_detail as a')
                ->leftJoin('sell as c','c.id','=','a.sell_id')
                ->leftJoin('storage_manage as b', 'a.materiel_type_id', '=', 'b.type_id')
                ->leftJoin('storage as d', 'd.id', '=', 'b.storage_id')
                ->leftJoin('materiel_type as e', 'e.id', '=', 'b.type_id')
                ->leftJoin('materiel_class as f', 'f.id', '=', 'e.materiel_class_id')
                ->where('e.id', $data['batch_no'])
                ->where('a.sell_id', $data['sell_id'])
                ->where('a.warehouse_id',$data['storage_id'])
                ->where('e.delete_flag', 0)
                ->where('b.delete_flag', 0)
                ->where('c.delete_flag', 0)
                ->where('c.out_status','!=',2)
                ->first();

            if(empty($sellGoodsBatchInfo)) {
                return ['code' => 1,'msg' => '销售单内无此批次信息','data' => ''];
            }
            if($sellGoodsBatchInfo['is_use_serial'] == 1) {

                return ['code' => 1,'msg' => '您开启了序列号，请选择序列号出库！','data' => ''];
            }
        if($sellGoodsBatchInfo['in_storage_num'] <= 0) {
            return ['code' => 1,'msg' => '商品库存数量不足','data' => ''];
        }

        if($sellGoodsBatchInfo['virtual_storage_num'] <= 0) {
            return ['code' => 1,'msg' => '商品虚拟库存数量不足','data' => ''];
        }
        if($sellGoodsBatchInfo['num'] - $sellGoodsBatchInfo['out_num'] <= 0){
            return ['code' => 1,'msg' => '销售单，商品已出库','data' => ''];
        }
        //库存数达到预警
        $sortFlag = 0;
        if($sellGoodsBatchInfo['in_storage_num']-1 <= $sellGoodsBatchInfo['alert_num']) {
            $sortFlag = 1;
        }
        $logOutInfo = [
            'type' => 4,
            'storage_batch_id' => "",
            'storage_id' => $sellGoodsBatchInfo['storage_id'],
            'storage_name' => $sellGoodsBatchInfo['storage_name'],
            'storage_address' => $sellGoodsBatchInfo['storage_address'],
            'curr_storage_manage_id' => $sellGoodsBatchInfo['storage_manage_id'],
            'materiel_class_id' => $sellGoodsBatchInfo['materiel_class_id'],
            'materiel_class_name' => $sellGoodsBatchInfo['class_name'],
            'materiel_class_no' => $sellGoodsBatchInfo['class_no'],
            'materiel_type_id' => $sellGoodsBatchInfo['materiel_type_id'],
            'materiel_name' => $sellGoodsBatchInfo['materiel_name'],
            'type_name' => $sellGoodsBatchInfo['type_name'],
            'materiel_no' => $sellGoodsBatchInfo['materiel_no'],
            'operate_num' => 1,
            'last_storage_num' => $sellGoodsBatchInfo['in_storage_num'],
            'next_storage_num' => $sellGoodsBatchInfo['in_storage_num'] - 1,
            'sell_price' => $sellGoodsBatchInfo['price'],
            'materiel_mean_cost' => $sellGoodsBatchInfo['materiel_mean_cost'],
            'all_id_type' => 2,
            'all_id' => $data['sell_id'],
            'user_id' => $data['user_id'],
            'main_id' => $data['main_id'],
            'out_storage_time' => $data['time'],
            'fact_out_time' => $data['time'],
            'created_at' => $data['time']
        ];

        MessageService::sendAlertSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $sellGoodsBatchInfo['alert_num'],
            $data,
            $sellGoodsBatchInfo['storage_id'],
            $sellGoodsBatchInfo['storage_name'],
            1
        );

       MessageService::sendShortSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $data,
            $sellGoodsBatchInfo['storage_id'],
            $sellGoodsBatchInfo['storage_name'],
       );

        MessageService::sendOutSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $sellGoodsBatchInfo['storage_name'],
           1,
            $data,
            $sellGoodsBatchInfo['storage_id'],
            $sellGoodsBatchInfo['alert_num'],
        );

      $list = SellGoodsDetail::select('num','out_num')
              ->where(['sell_id'=>$data['sell_id']])->get()->toArray();
      $num = 0;
      foreach ($list as $k=>$v){
         $num += $v['num']- $v['out_num'];
      }
        DB::beginTransaction();

        try {
            SellGoodsDetailModel::where('id', $sellGoodsBatchInfo['id'])
                ->increment('out_num', 1);
            StorageManageModel::where('id', $sellGoodsBatchInfo['storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw("in_storage_num - 1"),
                    'virtual_storage_num' => DB::raw("virtual_storage_num - 1"),
                    'sort_flag'=>$sortFlag
                ]);
            if($num == 1) {
                SellGoodsDetailModel::where('id', $sellGoodsBatchInfo['id'])
                ->update(['out_status'=> 1]);
                sellModel::where(['id'=>$data['sell_id']])->update(['out_status'=>2]);
            }else{
                sellModel::where(['id'=>$data['sell_id']])->update(['out_status'=>1]);
            }
            LogOutStorageModel::insert($logOutInfo);
            MaterielTypeModel::where(['id' => $sellGoodsBatchInfo['materiel_type_id']])->update(['price_last' => $sellGoodsBatchInfo['price']]);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('商品ID扫码，出库失败'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '商品ID扫码，出库失败!', 'data' => ''];
        }
    }

    //商品ID识别-销售单快速出库
    static private function sellGoodsBarCodeFastOut($data)
    {
        $sellGoodsBatchInfo = SellGoodsDetailModel::select(
            'a.id',
            'a.materiel_type_id',
            'e.materiel_name',
            'e.type_name',
            'e.materiel_no',
            'in_storage_num',
            'storage_id',
            'd.storage_name',
            'd.storage_address',
            'b.id as storage_manage_id',
            'e.materiel_class_id',
            'f.class_name',
            'f.class_no',
            'materiel_mean_cost',
            'alert_num',
            'a.num',
            'a.out_num',
            'a.price',
            'b.virtual_storage_num',
            'e.is_use_serial'
            )
            ->from('sell_goods_detail as a')
            ->leftJoin('sell as c','c.id','=','a.sell_id')
            ->leftJoin('storage_manage as b', 'a.materiel_type_id', '=', 'b.type_id')
            ->leftJoin('storage as d', 'd.id', '=', 'b.storage_id')
            ->leftJoin('materiel_type as e', 'e.id', '=', 'b.type_id')
            ->leftJoin('materiel_class as f', 'f.id', '=', 'e.materiel_class_id')
            ->where('e.bar_code', $data['batch_no'])
            ->where('a.sell_id', $data['sell_id'])
            ->where('a.warehouse_id',$data['storage_id'])
            ->where('e.delete_flag', 0)
            ->where('b.delete_flag', 0)
            ->where('c.delete_flag', 0)
            ->where('c.out_status','!=',2)
            ->first()->toArray();

            if(empty($sellGoodsBatchInfo)) {
                return ['code' => 1,'msg' => '销售单内无此批次信息','data' => ''];
            }
            if($sellGoodsBatchInfo['is_use_serial'] == 1) {

                return ['code' => 1,'msg' => '您开启了序列号，请选择序列号出库！','data' => ''];
            }
            if($sellGoodsBatchInfo['in_storage_num'] <= 0) {
                return ['code' => 1,'msg' => '商品库存数量不足','data' => ''];
            }

            if($sellGoodsBatchInfo['virtual_storage_num'] <= 0) {
                return ['code' => 1,'msg' => '商品虚拟库存数量不足','data' => ''];
            }
            if($sellGoodsBatchInfo['num'] - $sellGoodsBatchInfo['out_num'] <= 0){
                return ['code' => 1,'msg' => '销售单，商品已出库','data' => ''];
            }
            //库存数达到预警
            $sortFlag = 0;
            if($sellGoodsBatchInfo['in_storage_num']-1 <= $sellGoodsBatchInfo['alert_num']) {
                $sortFlag = 1;
            }
            $logOutInfo = [
                'type' => 4,
                'storage_batch_id' => "",
                'storage_id' => $sellGoodsBatchInfo['storage_id'],
                'storage_name' => $sellGoodsBatchInfo['storage_name'],
                'storage_address' => $sellGoodsBatchInfo['storage_address'],
                'curr_storage_manage_id' => $sellGoodsBatchInfo['storage_manage_id'],
                'materiel_class_id' => $sellGoodsBatchInfo['materiel_class_id'],
                'materiel_class_name' => $sellGoodsBatchInfo['class_name'],
                'materiel_class_no' => $sellGoodsBatchInfo['class_no'],
                'materiel_type_id' => $sellGoodsBatchInfo['materiel_type_id'],
                'materiel_name' => $sellGoodsBatchInfo['materiel_name'],
                'type_name' => $sellGoodsBatchInfo['type_name'],
                'materiel_no' => $sellGoodsBatchInfo['materiel_no'],
                'operate_num' => 1,
                'last_storage_num' => $sellGoodsBatchInfo['in_storage_num'],
                'next_storage_num' => $sellGoodsBatchInfo['in_storage_num'] - 1,
                'sell_price' => $sellGoodsBatchInfo['price'],
                'materiel_mean_cost' => $sellGoodsBatchInfo['materiel_mean_cost'],
                'all_id_type' => 2,
                'all_id' => $data['sell_id'],
                'user_id' => $data['user_id'],
                'main_id' => $data['main_id'],
                'out_storage_time' => $data['time'],
                'fact_out_time' => $data['time'],
                'created_at' => $data['time']
            ];

            MessageService::sendAlertSms(
                $sellGoodsBatchInfo['materiel_name'],
                $sellGoodsBatchInfo['type_name'],
                $sellGoodsBatchInfo['in_storage_num'] - 1,
                $sellGoodsBatchInfo['alert_num'],
                $data,
                $sellGoodsBatchInfo['storage_id'],
                $sellGoodsBatchInfo['storage_name'],
                1
                );

            MessageService::sendShortSms(
                $sellGoodsBatchInfo['materiel_name'],
                $sellGoodsBatchInfo['type_name'],
                $sellGoodsBatchInfo['in_storage_num'] - 1,
                $data,
                $sellGoodsBatchInfo['storage_id'],
                $sellGoodsBatchInfo['storage_name'],
                );

            MessageService::sendOutSms(
                $sellGoodsBatchInfo['materiel_name'],
                $sellGoodsBatchInfo['type_name'],
                $sellGoodsBatchInfo['in_storage_num'] - 1,
                $sellGoodsBatchInfo['storage_name'],
                1,
                $data,
                $sellGoodsBatchInfo['storage_id'],
                $sellGoodsBatchInfo['alert_num'],
                );

            $list = SellGoodsDetail::select('num','out_num')
            ->where(['sell_id'=>$data['sell_id']])->get()->toArray();
            $num = 0;
            foreach ($list as $k=>$v){
                $num += $v['num']- $v['out_num'];
            }
            DB::beginTransaction();

            try {
                SellGoodsDetailModel::where('id', $sellGoodsBatchInfo['id'])
                ->increment('out_num', 1);
                StorageManageModel::where('id', $sellGoodsBatchInfo['storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw("in_storage_num - 1"),
                    'virtual_storage_num' => DB::raw("virtual_storage_num - 1"),
                    'sort_flag'=>$sortFlag
                ]);
                if($num == 1) {
                    SellGoodsDetailModel::where('id', $sellGoodsBatchInfo['id'])
                    ->update(['out_status'=> 1]);
                    sellModel::where(['id'=>$data['sell_id']])->update(['out_status'=>2]);
                }else{
                    sellModel::where(['id'=>$data['sell_id']])->update(['out_status'=>1]);
                }
                LogOutStorageModel::insert($logOutInfo);
                MaterielTypeModel::where(['id' => $sellGoodsBatchInfo['materiel_type_id']])->update(['price_last' => $sellGoodsBatchInfo['price']]);
                DB::commit();
                return ['code' => 0, 'msg' => 'success', 'data' => ''];
            }
            catch(Exception $e) {
                DB::rollBack();
                Log::debug('条形码扫码出库失败'.var_export($e->getMessage(), true));
                return ['code' => 1, 'msg' => '条形码扫码,出库失败!', 'data' => ''];
            }
    }

    //销售单快速出库(序列号)
    static private function serialMaterielSellFastOut($data)
    {
            $info = MaterielTypeModel::where(['id'=>$data['goods_id'],'delete_flag'=>0])->first();
            if(empty($info)) {
                return ['code' => 1,'msg' => '序列号商品不存在，无法出库','data' => ''];
            }
            $sellGoodsBatchInfo = SellGoodsDetailModel::select(
            'a.id',
            'a.materiel_type_id',
            'f.materiel_name',
            'f.type_name',
            'f.materiel_no',
            'a.num',
            'a.out_num',
            'in_storage_num',
            'storage_id',
            'e.storage_name',
            'e.storage_address',
            'd.id as storage_manage_id',
            'f.materiel_class_id',
            'g.class_name',
            'g.class_no',
            'materiel_mean_cost',
            'alert_num',
            'c.id as serial_id',
            'a.price',
            'c.status as serial_status',
            'd.virtual_storage_num'
            )
            ->from('sell_goods_detail as a')
            ->leftJoin('serial_number as c', 'c.goods_id', '=', 'a.materiel_type_id')
            ->leftJoin('storage_manage as d', 'd.id', '=', 'c.storage_manage_id')
            ->leftJoin('storage as e', 'e.id', '=', 'd.storage_id')
            ->leftJoin('materiel_type as f', 'f.id', '=', 'd.type_id')
            ->leftJoin('materiel_class as g', 'g.id', '=', 'f.materiel_class_id')
            ->where('c.serial_no', $data['batch_no'])
            ->where('c.goods_id', $data['goods_id'])
            ->where('a.warehouse_id',$data['storage_id'])
            ->where('a.sell_id', $data['sell_id'])
            ->first();

            //商品已设置批次号
            if(!empty($sellGoodsBatchInfo)) {
                if($sellGoodsBatchInfo['num'] == $sellGoodsBatchInfo['out_num']) {
                    return ['code' => 1,'msg' => '该商品已全部出库，无法重复操作','data' => ''];
                }

                if($sellGoodsBatchInfo['serial_status'] == 0) {
                    return ['code' => 1,'msg' => '该商品序列号，已使用','data' => ''];
                }
            }else {
                    return ['code' => 1,'msg' => '没有找到对应的商品，非常抱歉！','data' => ''];
            }

            if($sellGoodsBatchInfo['in_storage_num'] <= 0) {
                return ['code' => 1,'msg' => '商品库存数量不足','data' => ''];
            }
            if($sellGoodsBatchInfo['virtual_storage_num'] <= 0) {
                return ['code' => 1,'msg' => '商品虚拟库存数量不足','data' => ''];
            }
        //库存数达到预警
        $sortFlag = 0;
        if($sellGoodsBatchInfo['in_storage_num']-1 <= $sellGoodsBatchInfo['alert_num']) {
            $sortFlag = 1;
        }
            $logOutInfo = [
                'type' => 4,
                'storage_id' => $sellGoodsBatchInfo['storage_id'],
                'storage_name' => $sellGoodsBatchInfo['storage_name'],
                'storage_address' => $sellGoodsBatchInfo['storage_address'],
                'curr_storage_manage_id' => $sellGoodsBatchInfo['storage_manage_id'],
                'materiel_class_id' => $sellGoodsBatchInfo['materiel_class_id'],
                'materiel_class_name' => $sellGoodsBatchInfo['class_name'],
                'materiel_class_no' => $sellGoodsBatchInfo['class_no'],
                'materiel_type_id' => $sellGoodsBatchInfo['materiel_type_id'],
                'materiel_name' => $sellGoodsBatchInfo['materiel_name'],
                'type_name' => $sellGoodsBatchInfo['type_name'],
                'materiel_no' => $sellGoodsBatchInfo['materiel_no'],
                'operate_num' => 1,
                'last_storage_num' => $sellGoodsBatchInfo['in_storage_num'],
                'next_storage_num' => $sellGoodsBatchInfo['in_storage_num'] - 1,
                'sell_price' => $sellGoodsBatchInfo['price'],
                'materiel_mean_cost' => $sellGoodsBatchInfo['materiel_mean_cost'],
                'all_id_type' => 2,
                'all_id' => $data['sell_id'],
                'user_id' => $data['user_id'],
                'main_id' => $data['main_id'],
                'out_storage_time' => $data['time'],
                'fact_out_time' => $data['time'],
                'created_at' => $data['time'],
                'serial_number'=>$data['batch_no']
            ];

                MessageService::sendAlertSms(
                    $sellGoodsBatchInfo['materiel_name'],
                    $sellGoodsBatchInfo['type_name'],
                    $sellGoodsBatchInfo['in_storage_num'] - 1,
                    $sellGoodsBatchInfo['alert_num'],
                    $data,
                    $sellGoodsBatchInfo['storage_id'],
                    $sellGoodsBatchInfo['storage_name'],
                    1
                );

                MessageService::sendShortSms(
                    $sellGoodsBatchInfo['materiel_name'],
                    $sellGoodsBatchInfo['type_name'],
                    $sellGoodsBatchInfo['in_storage_num'] - 1,
                    $data,
                    $sellGoodsBatchInfo['storage_id'],
                    $sellGoodsBatchInfo['storage_name'],
                );

                MessageService::sendOutSms(
                    $sellGoodsBatchInfo['materiel_name'],
                    $sellGoodsBatchInfo['type_name'],
                    $sellGoodsBatchInfo['in_storage_num'] - 1,
                    $sellGoodsBatchInfo['storage_name'],
                    1,
                    $data,
                    $sellGoodsBatchInfo['storage_id'],
                    $sellGoodsBatchInfo['alert_num'],
                );

        DB::beginTransaction();

        try {
            SellGoodsDetailModel::where('id', $sellGoodsBatchInfo['id'])
            ->increment('out_num', 1);
            StorageManageModel::where('id', $sellGoodsBatchInfo['storage_manage_id'])
            ->update([
                'in_storage_num' => DB::raw("in_storage_num - 1"),
                'virtual_storage_num' => DB::raw("virtual_storage_num - 1"),
                'sort_flag'=>$sortFlag
            ]);
            LogOutStorageModel::insert($logOutInfo);
            $arr=[
                'status'  => 1,
                'main_id' => $data['main_id'],
                'sell_id' => $data['sell_id'],
                'serial_number' => $data['batch_no'],
                'type_id' => $sellGoodsBatchInfo['materiel_type_id']
            ];
            SellOutSerialNumbersModel::insert($arr);
            SerialNumberModel::where([
                'serial_no' => $data['batch_no'],
                'goods_id'  => $sellGoodsBatchInfo['materiel_type_id'],
                'storage_manage_id' => $sellGoodsBatchInfo['storage_manage_id']
            ])->update(['status'=>0]);
            MaterielTypeModel::where(['id' => $sellGoodsBatchInfo['materiel_type_id']])->update(['price_last' => $sellGoodsBatchInfo['price']]);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('序列号扫码，出库失败'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '序列号扫码，出库失败！', 'data' => ''];
        }
    }

    /**
     * 清除库存信息
     * @param $data
     * AUTHOR  : Sun Wu
     * DateTime: 2022/7/13 16:50
     * @return array
     */
    static public function clear($data)
    {
        DB::beginTransaction();

        $storageManageInfo = StorageManageModel::where([
            'storage_id' => $data['id'],
            'delete_flag' => 0
        ])->get()->toArray();

        if(empty($storageManageInfo)) {
            return ['code' => 1, 'msg' => '要清除的目标库存信息不存在，无法操作，请重试', 'data' => ''];
        }

        try {
            //获取库存id
            $storageManageId = [];
            foreach($storageManageInfo as $value) {
                $storageManageId[] = $value['id'];
            }

            //清除库存信息
            StorageManageModel::whereIn('id', $storageManageId)
                ->update([
                    'in_storage_num' => 0,
                    'virtual_storage_num' => 0,
                    'delete_flag' => 0
                ]);

            //清除库存批次信息
            StorageBatchModel::whereIn('storage_manage_id', $storageManageId)
                ->update([
                    'batch_left_num' => 0
                ]);
            SerialNumberModel::whereIn('storage_manage_id', $storageManageId)->delete();
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('清除批次信息'.var_export($e->getMessage()));
            return ['code' => 1, 'msg' => '清除失败', 'data' => ''];
        }
    }

    //批量入库
    public static function directInStorageSeveral($data, $time)
    {
        $data['alert_num'] = $data['status'] == 1?$data['alert_num']:0;
        $data['remark'] = empty($data['remark'])?'':$data['remark'];

        if(!empty($data['goods_info'])){
            $goods = json_decode($data['goods_info'],true);

            foreach ($goods as $key => $value) {
                $validator = Validator::make($value, [
                    'materiel_name' => 'required',
//                    'type_name' => 'required',
                    'num' => 'required|numeric|min:0',
                ]);
                //参数错误响应
                if ($info = $validator->errors()->first()) {
                    return ['code' => 1, 'msg' => $info, 'data' => ''];
                }
            }
        }

        DB::beginTransaction();

        try {
            self::storeGoods($data, $time);
            DB::commit();
        } catch (Exception $e) {
            DB::rollback();
            Log::debug('新建入库(直接入库：'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];

        }

        return ['code' => 0, 'msg' => 'success', 'data' => ''];
    }

    public static function directOutStorageSeveral($data)
    {
        if(!empty($data['goods_info'])){
            $goodsInfo = json_decode($data['goods_info'],true);

            $logData = [];
            $outStorageData = [];
            $outSerialData = [];
            foreach($goodsInfo as $value) {
                $storageManageInfo = StorageManageModel::select(
                    'a.id',
                    'a.storage_id',
                    'a.materiel_class_id',
                    'a.type_id',
                    'a.in_storage_num',
                    'a.materiel_mean_cost',
                    'b.class_name as materiel_class_name',
                    'b.class_no as materiel_class_no',
                    'c.is_use_serial',
                    'c.materiel_name',
                    'c.type_name',
                    'c.materiel_no',
                    'd.storage_name',
                    'd.storage_address',
                    'a.alert_num',
                    'a.virtual_storage_num',
                    'a.shelf_id',
                    'a.location_id',
                    'c.is_use_serial'
                )
                    ->from('storage_manage as a')
                    ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                    ->leftJoin('materiel_type as c', 'c.id', '=', 'a.type_id')
                    ->leftJoin('storage as d', 'd.id', '=', 'a.storage_id')
                    ->where([
                        'a.id' => $value['storageManageId'],
                        'a.main_id' => $data['main_id'],
                        'a.delete_flag' => 0
                    ])->first();

                if($value['num'] > $storageManageInfo['virtual_storage_num']) {
                    return ['code' => 1, 'msg' => '商品:'.$storageManageInfo['materiel_name'].'可用库存数不足，请重试', 'data' => ''];
                }

                if($storageManageInfo['is_use_serial']) {
                    if($value['serial_no'] == '') {
                        return ['code' => 1, 'msg' => '商品:'.$storageManageInfo['materiel_name'].'请选择序列号', 'data' => ''];
                    }

                    $serialData = array_unique(array_filter(explode(',', $value['serial_no'])));

                    if($value['num'] < count($serialData)) {
                        $shortNum = count($serialData) - $value['num'];
                        return ['code' => 1, 'msg' => '商品:'.$storageManageInfo['materiel_name'].'出库数量X'.$value['num'].',序列号仍缺失X'.$shortNum, 'data' => ''];
                    }

                    if($value['num'] > count($serialData)) {
                        $shortNum = count($serialData) - $value['num'];
                        return ['code' => 1, 'msg' => '商品:'.$storageManageInfo['materiel_name'].'出库数量X'.$value['num'].',超出序列号所需数量'.$shortNum, 'data' => ''];
                    }

                    $serialInfo = SerialNumberModel::where([
                        'goods_id' => $storageManageInfo['type_id'],
                    ])
                        ->whereIn('serial_no', $serialData)
                        ->get()->toArray();

                    foreach($serialInfo as $serialValue) {
                        if(!$serialValue['status']) {
                            return [
                                'code' => 1,
                                'msg' => '商品:'.$storageManageInfo['materiel_name'].'出库数量X'.$value['num'].',序列号:'.$serialValue['serial_no'].'已被使用',
                                'data' => ''
                            ];
                        }
                        $outSerialData[] = [
                            'id' => $serialValue['id'],
                            'status' => 0
                        ];
                    }
                }

                MessageService::sendAlertSms(
                    $storageManageInfo['materiel_name'],
                    $storageManageInfo['type_name'],
                    $storageManageInfo['in_storage_num'] - $value['num'],
                    $storageManageInfo['alert_num'],
                    $data,
                    $storageManageInfo['storage_id'],
                    $storageManageInfo['storage_name'],
                    $value['num']
                );

                MessageService::sendShortSms(
                    $storageManageInfo['materiel_name'],
                    $storageManageInfo['type_name'],
                    $storageManageInfo['in_storage_num'] - $value['num'],
                    $data,
                    $storageManageInfo['storage_name'],
                    $storageManageInfo['storage_id']
                );

                MessageService::sendOutSms(
                    $storageManageInfo['materiel_name'],
                    $storageManageInfo['type_name'],
                    $storageManageInfo['in_storage_num'],
                    $storageManageInfo['storage_name'],
                    $value['num'],
                    $data,
                    $storageManageInfo['storage_id'],
                    $storageManageInfo['alert_num']
                );

                $logData[] = [
                    'type' => 2,//type;0:出库;1:调出;2:直接出库;
                    'storage_id' => $storageManageInfo['storage_id'],
                    'storage_name' => $storageManageInfo['storage_name'],
                    'storage_address' => $storageManageInfo['storage_address'],
                    'next_storage_id' => 0,
                    'next_storage_name' => '',
                    'next_storage_address' => '',
                    'curr_storage_manage_id' => $storageManageInfo['id'],
                    'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                    'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                    'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                    'materiel_type_id' => $storageManageInfo['type_id'],
                    'materiel_name' => $storageManageInfo['materiel_name'],
                    'type_name' => $storageManageInfo['type_name'],
                    'materiel_no' => $storageManageInfo['materiel_no'],
                    'operate_num' => $value['num'],
                    'last_storage_num' => $storageManageInfo['in_storage_num'],
                    'next_storage_num' => $storageManageInfo['in_storage_num'] - $value['num'],
                    'sell_price' => $storageManageInfo['materiel_mean_cost'],
                    'materiel_mean_cost' => $storageManageInfo['materiel_mean_cost'],
                    'remark' => empty($data['remark'])?'':$data['remark'],
                    'main_id' => $data['main_id'],
                    'user_id' => $data['user_id'],
                    'out_storage_time' => time(),
                    'created_at' => time(),
                    'serial_number'=>!empty($value['serial_no'])?$value['serial_no']:'',
                    'shelf_id' => $storageManageInfo['shelf_id'],
                    'location_id' => $storageManageInfo['location_id'],
                ];

                $outStorageData[] = [
                    'id' => $storageManageInfo['id'],
                    'in_storage_num' => $storageManageInfo['in_storage_num'] - $value['num'],
                    'virtual_storage_num' => $storageManageInfo['virtual_storage_num'] - $value['num'],
                ];
            }

            DB::beginTransaction();

            try {
                if(!empty($logData)) {
                    LogOutStorageModel::insert($logData);
                }

                if(!empty($outStorageData)) {
                    batch()->update(new StorageManageModel, $outStorageData, 'id');
                }

                if(!empty($outSerialData)) {
                    batch()->update(new SerialNumberModel, $outSerialData, 'id');
                }

                DB::commit();
                return ['code' => 0, 'msg' => 'success', 'data' => ''];
            }
            catch(Exception $e) {
                DB::rollBack();
                Log::debug('直接出库异常:'.var_export($e->getMessage(), true));
                return ['code' => '1', 'msg' => '直接出库异常,请重试', 'data' => ''];
            }
        }
        else {
            return ['code' => 1, 'msg' => '请选择要出库的商品', 'data' => ''];
        }
    }

    //批量出库
    public static function directOutStorageSeveral1($data)
    {
        if(!empty($data['goods_info'])){
            $goods = json_decode($data['goods_info'],true);

            foreach ($goods as $key => $value) {
                $validator = Validator::make($value, [
                    'storageManageId' => 'required',
                    'price' => 'required',
                    'num' => 'required|numeric|min:0',
                    'serial_no' => 'string',
                ]);
                //参数错误响应
                if ($info = $validator->errors()->first()) {
                    return ['code' => 1, 'msg' => $info, 'data' => ''];
                }
                //需出库物料信息
                $storageManageInfo = StorageManageModel::select(
                    'a.id',
                    'a.storage_id',
                    'a.materiel_class_id',
                    'a.type_id',
                    'a.in_storage_num',
                    'a.materiel_mean_cost',
                    'b.class_name as materiel_class_name',
                    'b.class_no as materiel_class_no',
                    'c.materiel_name',
                    'c.type_name',
                    'c.materiel_no',
                    'd.storage_name',
                    'd.storage_address',
                    'a.alert_num',
                    'a.virtual_storage_num',
                    'a.shelf_id',
                    'a.location_id',
                    'c.is_use_serial'
                    )
                    ->from('storage_manage as a')
                    ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                    ->leftJoin('materiel_type as c', 'c.id', '=', 'a.type_id')
                    ->leftJoin('storage as d', 'd.id', '=', 'a.storage_id')
                    ->where([
                        'a.id' => $value['storageManageId'],
                        'a.main_id' => $data['main_id'],
                        'a.delete_flag' => 0
                    ]);
                    if($data['is_use_shelf']) {

                       if(!empty($value['shelf_id']) && !empty($value['location_id'])){

                        $storageManageInfo->where('a.shelf_id', $value['shelf_id']);
                        $storageManageInfo->where('a.location_id', $value['location_id']);
                       }
                    }
                    $storageManageInfo = $storageManageInfo->first();

                    if(empty($storageManageInfo)) {
                        return ['code' => 1, 'msg' => '库存中不存在的物料，无法出库', 'data' => ''];
                    }

                    if($storageManageInfo['in_storage_num'] < $value['num']) {
                        return ['code' => 1, 'msg' => '操作数量超出实际库存数，无法完成出库,当前库存数为:'.$storageManageInfo['in_storage_num'], 'data' => ''];
                    }

                    if(empty($value['price'])){
                        $price = $storageManageInfo['materiel_mean_cost'];
                    }else{
                        $price = $value['price'];
                    }

                    if($storageManageInfo['is_use_serial'] == 1){
                       if(empty($value['serial_no'])) {
                           return ['code' => 1, 'msg' => '商品'.$storageManageInfo['materiel_name'].'请选择序列号出库!', 'data' => ''];

                       }
                    }
                    if($storageManageInfo['is_use_serial'] == 1 && !empty($value['serial_no'])){//序列号

                        $serial_no_array = explode(',',$value['serial_no']);

                        if(count($serial_no_array) != $value['num']){
                            return ['code' => 1, 'msg' => '商品'.$storageManageInfo['materiel_name'].'的序列号数量与出库数量不符，应选择序列号数量为：'.$value['num'], 'data' => ''];
                        }
                        foreach ($serial_no_array as $k => $serial_data){
                        //检查序列号是否使用
                        $number_info = SerialNumberModel::where(['goods_id' => $storageManageInfo['type_id'],'serial_no' => $serial_data])->first();

                        if(!empty($number_info)){
                            if($number_info['status'] == 0){
                                    return ['code' => 1, 'msg' => '商品'.$storageManageInfo['materiel_name'].'的序列号'.$serial_data.'已被使用', 'data' => ''];
                            }

                        DB::beginTransaction();

                        try {
                            SerialNumberModel::where(['serial_no' => $serial_data,'status' => SerialNumberModel::UNUSEDSTATUS,
                                'goods_id' => $number_info['goods_id'],
                            ])->update(['status' => SerialNumberModel::USEDSTATUS]);
                            if($storageManageInfo['in_storage_num'] < 1) {
                                return ['code' => 1, 'msg' => '操作数量超出实际库存数，无法完成出库,当前库存数为:'.$storageManageInfo['in_storage_num'], 'data' => ''];
                            }

                            if(empty($value['price'])){
                                $price = $storageManageInfo['materiel_mean_cost'];
                            }else{
                                $price = $value['price'];
                            }

                            $logData = [
                                'type' => 2,//type;0:出库;1:调出;2:直接出库;
                                'storage_id' => $storageManageInfo['storage_id'],
                                'storage_name' => $storageManageInfo['storage_name'],
                                'storage_address' => $storageManageInfo['storage_address'],
                                'next_storage_id' => 0,
                                'next_storage_name' => '',
                                'next_storage_address' => '',
                                'curr_storage_manage_id' => $storageManageInfo['id'],
                                'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                                'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                                'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                                'materiel_type_id' => $storageManageInfo['type_id'],
                                'materiel_name' => $storageManageInfo['materiel_name'],
                                'type_name' => $storageManageInfo['type_name'],
                                'materiel_no' => $storageManageInfo['materiel_no'],
                                'operate_num' => $value['num'],
                                'last_storage_num' => $storageManageInfo['in_storage_num'],
                                'next_storage_num' => $storageManageInfo['in_storage_num'] - 1,
                                'sell_price' => $price,
                                'materiel_mean_cost' => $price,
                                'remark' => empty($data['remark'])?'':$data['remark'],
                                'main_id' => $data['main_id'],
                                'user_id' => $data['user_id'],
                                'out_storage_time' => time(),
                                'created_at' => time(),
                                'serial_number'=>$serial_data,
                                'shelf_id' => $storageManageInfo['shelf_id'],
                                'location_id' => $storageManageInfo['location_id'],
                            ];

                            //出库操作记录日志
//                            $res = LogOutstorageModel::insert([
//                                'type' => 2,//type;0:出库;1:调出;2:直接出库;
//                                'storage_id' => $storageManageInfo['storage_id'],
//                                'storage_name' => $storageManageInfo['storage_name'],
//                                'storage_address' => $storageManageInfo['storage_address'],
//                                'next_storage_id' => 0,
//                                'next_storage_name' => '',
//                                'next_storage_address' => '',
//                                'curr_storage_manage_id' => $storageManageInfo['id'],
//                                'materiel_class_id' => $storageManageInfo['materiel_class_id'],
//                                'materiel_class_name' => $storageManageInfo['materiel_class_name'],
//                                'materiel_class_no' => $storageManageInfo['materiel_class_no'],
//                                'materiel_type_id' => $storageManageInfo['type_id'],
//                                'materiel_name' => $storageManageInfo['materiel_name'],
//                                'type_name' => $storageManageInfo['type_name'],
//                                'materiel_no' => $storageManageInfo['materiel_no'],
//                                'operate_num' => $value['num'],
//                                'last_storage_num' => $storageManageInfo['in_storage_num'],
//                                'next_storage_num' => $storageManageInfo['in_storage_num'] - 1,
//                                'sell_price' => $price,
//                                'materiel_mean_cost' => $price,
//                                'remark' => empty($data['remark'])?'':$data['remark'],
//                                'main_id' => $data['main_id'],
//                                'user_id' => $data['user_id'],
//                                'out_storage_time' => time(),
//                                'created_at' => time(),
//                                'serial_number'=>$serial_data,
//                                'shelf_id' => $storageManageInfo['shelf_id'],
//                                'location_id' => $storageManageInfo['location_id'],
//                            ]);

                            if($storageManageInfo['virtual_storage_num'] > 0) {
                                StorageManageModel::where('id', $value['storageManageId'])
                                ->update([
                                    'in_storage_num' => DB::raw('in_storage_num - 1'),
                                    'virtual_storage_num' => DB::raw('virtual_storage_num - 1')
                                ]);
                            } else {
                                throw new Exception('可用库存数不足，无法出库');
//                                StorageManageModel::where('id', $value['storageManageId'])
//                                ->update([
//                                    'in_storage_num' => DB::raw('in_storage_num - 1'),
//                                ]);
                            }
                            MessageService::sendAlertSms(
                                $storageManageInfo['materiel_name'],
                                $storageManageInfo['type_name'],
                                $storageManageInfo['in_storage_num'] - 1,
                                $storageManageInfo['alert_num'],
                                $data,
                                $storageManageInfo['storage_id'],
                                $storageManageInfo['storage_name'],
                                $value['num']
                                );

                            MessageService::sendShortSms(
                                $storageManageInfo['materiel_name'],
                                $storageManageInfo['type_name'],
                                $storageManageInfo['in_storage_num'] - 1,
                                $data,
                                $storageManageInfo['storage_name'],
                                $storageManageInfo['storage_id']
                                );

                            MessageService::sendOutSms(
                                $storageManageInfo['materiel_name'],
                                $storageManageInfo['type_name'],
                                $storageManageInfo['in_storage_num'],
                                $storageManageInfo['storage_name'],
                                $value['num'],
                                $data,
                                $storageManageInfo['storage_id'],
                                $storageManageInfo['alert_num']
                                );

                            DB::commit();
                        } catch(Exception $e) {
                            DB::rollBack();
                            Log::debug('出库'.var_export($e->getMessage(), true));
                            return ['code' => 0, 'msg' => '出库失败', 'data' => ''];

                        }
                        }else{
                            return ['code' => 1, 'msg' => '序列号不存在', 'data' => ''];
                        }

                      }
                    }else{//没有开启序列号
                        DB::beginTransaction();
                        try {
                                //出库操作记录日志
                                $res = LogOutstorageModel::insert([
                                    'type' => 2,//type;0:出库;1:调出;2:直接出库;
                                    'storage_id' => $storageManageInfo['storage_id'],
                                    'storage_name' => $storageManageInfo['storage_name'],
                                    'storage_address' => $storageManageInfo['storage_address'],
                                    'next_storage_id' => 0,
                                    'next_storage_name' => '',
                                    'next_storage_address' => '',
                                    'curr_storage_manage_id' => $storageManageInfo['id'],
                                    'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                                    'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                                    'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                                    'materiel_type_id' => $storageManageInfo['type_id'],
                                    'materiel_name' => $storageManageInfo['materiel_name'],
                                    'type_name' => $storageManageInfo['type_name'],
                                    'materiel_no' => $storageManageInfo['materiel_no'],
                                    'operate_num' => $value['num'],
                                    'last_storage_num' => $storageManageInfo['in_storage_num'],
                                    'next_storage_num' => $storageManageInfo['in_storage_num'] - $value['num'],
                                    'sell_price' => $price,
                                    'materiel_mean_cost' => $price,
                                    'remark' => empty($data['remark'])?'':$data['remark'],
                                    'main_id' => $data['main_id'],
                                    'user_id' => $data['user_id'],
                                    'out_storage_time' => time(),
                                    'created_at' => time(),

                                    'shelf_id' => $storageManageInfo['shelf_id'],
                                    'location_id' => $storageManageInfo['location_id'],
                                ]);

                                if($storageManageInfo['virtual_storage_num'] > 0) {
                                    StorageManageModel::where('id', $value['storageManageId'])
                                    ->update([
                                        'in_storage_num' => DB::raw('in_storage_num - '.$value['num']),
                                        'virtual_storage_num' => DB::raw('virtual_storage_num - '.$value['num'])
                                    ]);
                                } else {
                                    throw new Exception('可用库存数不足，无法出库');
//                                    StorageManageModel::where('id', $value['storageManageId'])
//                                    ->update([
//                                        'in_storage_num' => DB::raw('in_storage_num - '.$value['num']),
//                                    ]);
                                }

                                MessageService::sendAlertSms(
                                    $storageManageInfo['materiel_name'],
                                    $storageManageInfo['type_name'],
                                    $storageManageInfo['in_storage_num'] - $value['num'],
                                    $storageManageInfo['alert_num'],
                                    $data,
                                    $storageManageInfo['storage_id'],
                                    $storageManageInfo['storage_name'],
                                    $value['num']
                                    );

                                MessageService::sendShortSms(
                                    $storageManageInfo['materiel_name'],
                                    $storageManageInfo['type_name'],
                                    $storageManageInfo['in_storage_num'] - $value['num'],
                                    $data,
                                    $storageManageInfo['storage_name'],
                                    $storageManageInfo['storage_id']
                                    );

                                MessageService::sendOutSms(
                                    $storageManageInfo['materiel_name'],
                                    $storageManageInfo['type_name'],
                                    $storageManageInfo['in_storage_num'],
                                    $storageManageInfo['storage_name'],
                                    $value['num'],
                                    $data,
                                    $storageManageInfo['storage_id'],
                                    $storageManageInfo['alert_num']
                                    );

                                DB::commit();
                        } catch(Exception $e) {
                            DB::rollBack();
                            Log::debug('出库'.var_export($e->getMessage(), true));
                            return ['code' => 0, 'msg' => '出库失败！', 'data' => ''];

                        }
                    }
                }
        }

        if(!empty($data['package_info'])){
            DB::beginTransaction();

            try {
                $package_data = json_decode($data['package_info'],true);
                foreach ($package_data as $v){
                    $package = PackageModel::where(['id' => $v['package_id']])->first();

                    if (empty($package)) {
                        return [
                            'code' => 1,
                            'msg' => '销售单内指定的套餐不存在，无法出库',
                            'data' => ''
                        ];
                    }

                        $logpackageNewId = LogPackageModel::insertGetId([
                        'package_id' => $v['package_id'],
                        'package_name' => $package['package_name'],
                        'num' => $v['num'],
                        'sell_price' => $v['price'],
                        'cost' => sprintf('%.6f', self::getPackageCost($v['package_id'])* $v['num']),
                        'out_storage_time' => time(),
                        'all_id_type' => 0,
                        'all_id' => 0,
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'remark' => empty($value['remark'])?'':$value['remark'],
                        'created_at' => time(),
                    ]);

                    foreach ($v['package_content'] as $value){
                        $package_info = PackageContentModel::where(['id' => $value['package_content_id'],'delete_flag' => 0])->first();
                        $storageManageInfo = StorageManageModel::where(['id' => $package_info['storage_manage_id']])->first();


                        if ($v['num']*$value['num'] > $storageManageInfo['in_storage_num']) {
                            return [
                                'code' => 1,
                                'msg' => '套餐可出库数量不足',
                                'data' => ''
                            ];
                        }

                        if ($v['num']*$value['num'] > $storageManageInfo['virtual_storage_num']) {
                            throw new Exception('可用库存数不足，无法出库');
                        }

                        StorageManageModel::where('id', $package_info['storage_manage_id'])
                            ->update([
                                'in_storage_num' => DB::raw('in_storage_num - '.$value['num'] * $v['num']),
                                'virtual_storage_num' => DB::raw('virtual_storage_num - '.$value['num'] * $v['num'])
                            ]);

                        LogPackageContentModel::insert([
                            'log_package_id' => $logpackageNewId,
                            'package_id' => $package_info['package_id'],
                            'storage_id' => $storageManageInfo['storage_id'],
                            'storage_name' => $storageManageInfo['storage_name'],
                            'storage_address' => $storageManageInfo['storage_address'],
                            'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                            'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                            'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                            'materiel_type_id' => $storageManageInfo['type_id'],
                            'materiel_name' => $storageManageInfo['materiel_name'],
                            'type_name' => $storageManageInfo['type_name'],
                            'materiel_no' => $storageManageInfo['materiel_no'],
                            'operate_num' => $value['num'] * $v['num'],
                            'out_storage_manage_id' => $storageManageInfo['id'],
                            'last_storage_num' => $storageManageInfo['in_storage_num'],
                            'next_storage_num' => $storageManageInfo['in_storage_num'] - ($value['num'] * $v['num']),
                            'all_id_type' => 4,
                            'all_id' => 0,
                            'user_id' => $data['user_id'],
                            'main_id' => $data['main_id'],
                            'created_at' => time(),

                            'shelf_id' =>$storageManageInfo['shelf_id'],
                            'location_id' =>$storageManageInfo['location_id'],

                        ]);


                        $minfo = MaterielsTypeModel::select('is_use_serial')->where('id',$storageManageInfo['type_id'])->first();

                        if($minfo['is_use_serial'] == 1){
                            //处理序列号
                            $serial_no_res = SerialNumberModel::outSerialNumber($data['main_id'],$value['serial_no'],$value['num'], $storageManageInfo['type_id']);
                            if(!empty($serial_no_res['code'])){
                                throw new Exception($serial_no_res['msg']);
                            }
                        }

                    }
                    DB::commit();
                }
            }catch(Exception $e) {
                DB::rollBack();
                Log::debug('出库'.var_export($e->getMessage(), true));
                return ['code' => 0, 'msg' => '出库失败', 'data' => ''];

            }
        }
        return ['code' => 0, 'msg' => 'success', 'data' => ''];

    }

    //批量出库
    public static function batchDirectOutStorageSeveral($data)
    {
        if(!empty($data['goods_info'])){
            $goods = json_decode($data['goods_info'],true);

            foreach ($goods as $key => $value) {

                $validator = Validator::make($value, [
                    'storageManageId' => 'required',
                    'price' => 'required',
                    'num' => 'required|numeric|min:0',

                ]);
                //参数错误响应
                if ($info = $validator->errors()->first()) {
                    return ['code' => 1, 'msg' => $info, 'data' => ''];
                }
                //需出库物料信息
                $storageManageInfo = StorageManageModel::select(
                    'a.id',
                    'a.storage_id',
                    'a.materiel_class_id',
                    'a.type_id',
                    'a.in_storage_num',
                    'a.materiel_mean_cost',
                    'b.class_name as materiel_class_name',
                    'b.class_no as materiel_class_no',
                    'c.materiel_name',
                    'c.type_name',
                    'c.materiel_no',
                    'd.storage_name',
                    'd.storage_address',
                    'a.alert_num',
                    'a.virtual_storage_num',
                    'a.shelf_id',
                    'a.location_id',
                    'c.is_use_serial'
                    )
                    ->from('storage_manage as a')
                    ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                    ->leftJoin('materiel_type as c', 'c.id', '=', 'a.type_id')
                    ->leftJoin('storage as d', 'd.id', '=', 'a.storage_id')
                    ->where([
                        'a.id' => $value['storageManageId'],
                        'a.main_id' => $data['main_id'],
                        'a.delete_flag' => 0
                    ]);

                    if($data['is_use_shelf']) {
                        //不传默认使用默认库位
                        if(!empty($value['shelf_id']) && !empty($value['location_id'])){
                            /* $shelfId = ShelfService::get_default($value['storage_id'])['id'];
                            $locationId = ShelfService::get_default($shelfId,2)['id'];

                            $value['shelf_id'] = $shelfId;
                            $value['location_id'] = $locationId; */

                            $storageManageInfo->where('a.shelf_id', $value['shelf_id']);
                            $storageManageInfo->where('a.location_id', $value['location_id']);
                        }
                    }

                    $storageManageInfo = $storageManageInfo->first();

                if(empty($value['price'])){
                    $price = $storageManageInfo['materiel_mean_cost'];
                }else{
                    $price = $value['price'];
                }

                LogOutstorageModel::insert([
                    'type' => 2,//type;0:出库;1:调出;2:直接出库;
                    'storage_id' => $storageManageInfo['storage_id'],
                    'storage_name' => $storageManageInfo['storage_name'],
                    'storage_address' => $storageManageInfo['storage_address'],
                    'next_storage_id' => 0,
                    'next_storage_name' => '',
                    'next_storage_address' => '',
                    'curr_storage_manage_id' => $storageManageInfo['id'],
                    'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                    'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                    'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                    'materiel_type_id' => $storageManageInfo['type_id'],
                    'materiel_name' => $storageManageInfo['materiel_name'],
                    'type_name' => $storageManageInfo['type_name'],
                    'materiel_no' => $storageManageInfo['materiel_no'],
                    'operate_num' => $value['num'],
                    'last_storage_num' => $storageManageInfo['in_storage_num'],
                    'next_storage_num' => $storageManageInfo['in_storage_num'] - $value['num'],
                    'sell_price' => $price,
                    'materiel_mean_cost' => $price,
                    'remark' => empty($data['remark'])?'':$data['remark'],
                    'main_id' => $data['main_id'],
                    'user_id' => $data['user_id'],
                    'out_storage_time' => time(),
                    'created_at' => time(),
                    'serial_number'=>!empty($value['serial_no'])?$value['serial_no']:'',
                    'shelf_id' => $storageManageInfo['shelf_id'],
                    'location_id' => $storageManageInfo['location_id'],
                ]);


                if(empty($storageManageInfo)) {
                        return ['code' => 1, 'msg' => '库存中不存在的物料，无法出库', 'data' => ''];
                    }
                    if($storageManageInfo['is_use_serial'] == 1){
                        if(empty($value['serial_no'])) {
                            return ['code' => 1, 'msg' => '商品'.$storageManageInfo['materiel_name'].'请选择序列号出库!', 'data' => ''];

                        }
                    }
                    if($storageManageInfo['is_use_serial'] == 1 && !empty($value['serial_no'])){//序列号

                        $serial_no_array = explode(',',$value['serial_no']);
                        if(count($serial_no_array) != $value['num']){
                            return ['code' => 1, 'msg' => '商品'.$storageManageInfo['materiel_name'].'的序列号数量与出库数量不符，应选择序列号数量为：'.$value['num'], 'data' => ''];
                        }

                        foreach ($serial_no_array as $k => $serial_data){
                            //检查序列号是否使用
                            $number_info = SerialNumberModel::where(['goods_id' => $storageManageInfo['type_id'],'serial_no' => $serial_data])->first();

                            if(!empty($number_info)){
                                if($number_info['status'] == 0){
                                    return ['code' => 1, 'msg' => '商品'.$storageManageInfo['materiel_name'].'的序列号'.$serial_data.'已被使用', 'data' => ''];
                                }

                        DB::beginTransaction();

                        try {
                            SerialNumberModel::where(['serial_no' => $serial_data,'status' => SerialNumberModel::UNUSEDSTATUS,
                                'goods_id' => $number_info['goods_id'],
                            ])->update(['status' => SerialNumberModel::USEDSTATUS]);
                            if($storageManageInfo['in_storage_num'] < 1) {
                                return ['code' => 1, 'msg' => '操作数量超出实际库存数，无法完成出库,当前库存数为:'.$storageManageInfo['in_storage_num'], 'data' => ''];
                            }

                            if($storageManageInfo['virtual_storage_num'] > 0) {
                                StorageManageModel::where('id', $value['storageManageId'])
                                ->update([
                                    'in_storage_num' => DB::raw('in_storage_num - 1'),
                                    'virtual_storage_num' => DB::raw('virtual_storage_num - 1')
                                ]);
                            } else {
                                throw new Exception('可用库存数不足，无法出库');
//                                StorageManageModel::where('id', $value['storageManageId'])
//                                ->update([
//                                    'in_storage_num' => DB::raw('in_storage_num - 1'),
//                                ]);
                            }
                            MessageService::sendAlertSms(
                                $storageManageInfo['materiel_name'],
                                $storageManageInfo['type_name'],
                                $storageManageInfo['in_storage_num'] - 1,
                                $storageManageInfo['alert_num'],
                                $data,
                                $storageManageInfo['storage_id'],
                                $storageManageInfo['storage_name'],
                                $value['num']
                                );

                            MessageService::sendShortSms(
                                $storageManageInfo['materiel_name'],
                                $storageManageInfo['type_name'],
                                $storageManageInfo['in_storage_num'] - 1,
                                $data,
                                $storageManageInfo['storage_name'],
                                $storageManageInfo['storage_id']
                                );

                            MessageService::sendOutSms(
                                $storageManageInfo['materiel_name'],
                                $storageManageInfo['type_name'],
                                $storageManageInfo['in_storage_num'],
                                $storageManageInfo['storage_name'],
                                $value['num'],
                                $data,
                                $storageManageInfo['storage_id'],
                                $storageManageInfo['alert_num']
                                );

                            DB::commit();
                        } catch(Exception $e) {
                            DB::rollBack();
                            Log::debug('出库'.var_export($e->getMessage(), true));
                            return ['code' => 1, 'msg' => '出库失败！', 'data' => ''];

                        }
                        }else{
                            return ['code' => 1, 'msg' => '序列号不存在', 'data' => ''];
                        }
                      }

                    }else{

                        if(!empty($value['batch_info'])){

                        foreach ($value['batch_info'] as $k =>$v){
                            //需出库物料信息
                            $storageManageInfo = StorageManageModel::select(
                                'a.id',
                                'a.storage_id',
                                'a.materiel_class_id',
                                'a.type_id',
                                'a.in_storage_num',
                                'a.materiel_mean_cost',
                                'b.class_name as materiel_class_name',
                                'b.class_no as materiel_class_no',
                                'c.materiel_name',
                                'c.type_name',
                                'c.materiel_no',
                                'd.storage_name',
                                'd.storage_address',
                                'a.alert_num',
                                'a.virtual_storage_num',
                                'a.shelf_id',
                                'a.location_id',
                                'c.is_use_serial',
                                'e.batch_left_num'
                                )
                                ->from('storage_manage as a')
                                ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                                ->leftJoin('materiel_type as c', 'c.id', '=', 'a.type_id')
                                ->leftJoin('storage as d', 'd.id', '=', 'a.storage_id')
                                ->leftJoin('storage_batch as e','e.storage_manage_id', '=', 'a.id')
                                ->where([
                                    'a.id' => $value['storageManageId'],
                                    'a.main_id' => $data['main_id'],
                                    'a.delete_flag' => 0,
                                    'e.id'=>$v['batch_id']
                                ]);
                                if($data['is_use_shelf']) {
                                    if(!empty($value['shelf_id']) && !empty($value['location_id'])){
                                    $storageManageInfo->where('a.shelf_id', $value['shelf_id']);
                                    $storageManageInfo->where('a.location_id', $value['location_id']);
                                    }
                                }
                                $storageManageInfo = $storageManageInfo->first()->toArray();

                                if(empty($storageManageInfo)) {
                                    return ['code' => 1, 'msg' => '库存中不存在的物料，无法出库', 'data' => ''];
                                }
                                if($storageManageInfo['in_storage_num'] < $v['num']) {
                                    return ['code' => 1, 'msg' => '操作数量超出实际库存数，无法完成出库,当前库存数为:'.$storageManageInfo['in_storage_num'], 'data' => ''];
                                }

                            if($storageManageInfo['virtual_storage_num'] < $v['num']) {
                                throw new Exception('可用库存数不足，无法出库');
                            }

                                if($storageManageInfo['batch_left_num'] < $v['num']) {

                                    return ['code' => 1, 'msg' => '商品批次库存不足，无法出库', 'data' => ''];
                                }
                        DB::beginTransaction();
                        try {
                                if(empty($value['price'])){
                                    $price = $storageManageInfo['materiel_mean_cost'];
                                }else{
                                    $price = $value['price'];
                                }
                                //出库操作记录日志
                                $res = LogOutstorageModel::insert([
                                    'type' => 2,//type;0:出库;1:调出;2:直接出库;
                                    'storage_id' => $storageManageInfo['storage_id'],
                                    'storage_name' => $storageManageInfo['storage_name'],
                                    'storage_address' => $storageManageInfo['storage_address'],
                                    'next_storage_id' => 0,
                                    'next_storage_name' => '',
                                    'next_storage_address' => '',
                                    'curr_storage_manage_id' => $storageManageInfo['id'],
                                    'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                                    'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                                    'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                                    'materiel_type_id' => $storageManageInfo['type_id'],
                                    'materiel_name' => $storageManageInfo['materiel_name'],
                                    'type_name' => $storageManageInfo['type_name'],
                                    'materiel_no' => $storageManageInfo['materiel_no'],
                                    'operate_num' => $value['num'],
                                    'last_storage_num' => $storageManageInfo['in_storage_num'],
                                    'next_storage_num' => $storageManageInfo['in_storage_num'] - $v['num'],
                                    'sell_price' => $price,
                                    'materiel_mean_cost' => $price,
                                    'remark' => empty($data['remark'])?'':$data['remark'],
                                    'main_id' => $data['main_id'],
                                    'user_id' => $data['user_id'],
                                    'out_storage_time' => time(),
                                    'created_at' => time(),
                                    'shelf_id' => $storageManageInfo['shelf_id'],
                                    'location_id' => $storageManageInfo['location_id'],
                                    'storage_batch_id' => $v['batch_id']
                                ]);

                                if($storageManageInfo['virtual_storage_num'] > 0) {
                                    StorageManageModel::where('id', $value['storageManageId'])
                                    ->update([
                                        'in_storage_num' => DB::raw('in_storage_num - '.$v['num']),
                                        'virtual_storage_num' => DB::raw('virtual_storage_num - '.$v['num'])
                                    ]);
                                } else {
                                    throw new Exception('可用库存数不足，无法出库');
                                }
                                StorageBatchModel::where('id', $v['batch_id'])
                                ->decrement('batch_left_num', $v['num']);
                                MessageService::sendAlertSms(
                                    $storageManageInfo['materiel_name'],
                                    $storageManageInfo['type_name'],
                                    $storageManageInfo['in_storage_num'] - $value['num'],
                                    $storageManageInfo['alert_num'],
                                    $data,
                                    $storageManageInfo['storage_id'],
                                    $storageManageInfo['storage_name'],
                                    $value['num']
                                    );

                                MessageService::sendShortSms(
                                    $storageManageInfo['materiel_name'],
                                    $storageManageInfo['type_name'],
                                    $storageManageInfo['in_storage_num'] - $value['num'],
                                    $data,
                                    $storageManageInfo['storage_name'],
                                    $storageManageInfo['storage_id']
                                    );

                                MessageService::sendOutSms(
                                    $storageManageInfo['materiel_name'],
                                    $storageManageInfo['type_name'],
                                    $storageManageInfo['in_storage_num'],
                                    $storageManageInfo['storage_name'],
                                    $value['num'],
                                    $data,
                                    $storageManageInfo['storage_id'],
                                    $storageManageInfo['alert_num']
                                    );

                                DB::commit();
                        } catch(Exception $e) {
                            DB::rollBack();
                            Log::debug('出库'.var_export($e->getMessage(), true));
                            return ['code' => 1, 'msg' => '出库失败', 'data' => ''];

                        }
                        }
                }else{

                    //没有开通序列和批次号
                    DB::beginTransaction();

                    try {
                        if($storageManageInfo['in_storage_num'] < $value['num']) {
                            return ['code' => 1, 'msg' => '操作数量超出实际库存数，无法完成出库,当前库存数为:'.$storageManageInfo['in_storage_num'], 'data' => ''];
                        }

                        if(empty($value['price'])){
                            $price = $storageManageInfo['materiel_mean_cost'];
                        }else{
                            $price = $value['price'];
                        }

                        //出库操作记录日志
                        $res = LogOutstorageModel::insert([
                            'type' => 2,//type;0:出库;1:调出;2:直接出库;
                            'storage_id' => $storageManageInfo['storage_id'],
                            'storage_name' => $storageManageInfo['storage_name'],
                            'storage_address' => $storageManageInfo['storage_address'],
                            'next_storage_id' => 0,
                            'next_storage_name' => '',
                            'next_storage_address' => '',
                            'curr_storage_manage_id' => $storageManageInfo['id'],
                            'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                            'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                            'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                            'materiel_type_id' => $storageManageInfo['type_id'],
                            'materiel_name' => $storageManageInfo['materiel_name'],
                            'type_name' => $storageManageInfo['type_name'],
                            'materiel_no' => $storageManageInfo['materiel_no'],
                            'operate_num' => $value['num'],
                            'last_storage_num' => $storageManageInfo['in_storage_num'],
                            'next_storage_num' => $storageManageInfo['in_storage_num'] - $value['num'],
                            'sell_price' => $price,
                            'materiel_mean_cost' => $price,
                            'remark' => empty($data['remark'])?'':$data['remark'],
                            'main_id' => $data['main_id'],
                            'user_id' => $data['user_id'],
                            'out_storage_time' => time(),
                            'created_at' => time(),

                            'shelf_id' => $storageManageInfo['shelf_id'],
                            'location_id' => $storageManageInfo['location_id'],
                        ]);

                        if($storageManageInfo['virtual_storage_num'] > 0) {
                            StorageManageModel::where('id', $value['storageManageId'])
                            ->update([
                                'in_storage_num' => DB::raw('in_storage_num - '.$value['num']),
                                'virtual_storage_num' => DB::raw('virtual_storage_num - '.$value['num'])
                            ]);
                        } else {
                            throw new Exception('可用库存数不足，无法出库');
//                            StorageManageModel::where('id', $value['storageManageId'])
//                            ->update([
//                                'in_storage_num' => DB::raw('in_storage_num - '.$value['num']),
//                            ]);
                        }

                        MessageService::sendAlertSms(
                         $storageManageInfo['materiel_name'],
                         $storageManageInfo['type_name'],
                         $storageManageInfo['in_storage_num'] - $value['num'],
                         $storageManageInfo['alert_num'],
                         $data,
                         $storageManageInfo['storage_id'],
                         $storageManageInfo['storage_name'],
                         $value['num']
                         );

                        MessageService::sendShortSms(
                        $storageManageInfo['materiel_name'],
                        $storageManageInfo['type_name'],
                        $storageManageInfo['in_storage_num'] - $value['num'],
                        $data,
                        $storageManageInfo['storage_name'],
                        $storageManageInfo['storage_id']
                        );

                        MessageService::sendOutSms(
                        $storageManageInfo['materiel_name'],
                        $storageManageInfo['type_name'],
                        $storageManageInfo['in_storage_num'],
                        $storageManageInfo['storage_name'],
                        $value['num'],
                        $data,
                        $storageManageInfo['storage_id'],
                        $storageManageInfo['alert_num']
                        );

                        DB::commit();
                    } catch(Exception $e) {
                        DB::rollBack();
                        Log::debug('出库'.var_export($e->getMessage(), true));
                        return ['code' => 1, 'msg' => '出库失败！', 'data' => ''];

                    }
                }
            }
            }
        }

        if(!empty($data['package_info'])){
            DB::beginTransaction();

            try {
                $package_data = json_decode($data['package_info'],true);
                foreach ($package_data as $v){
                    $package = PackageModel::where(['id' => $v['package_id']])->first();

                    if (empty($package)) {
                        return [
                            'code' => 1,
                            'msg' => '销售单内指定的套餐不存在，无法出库',
                            'data' => ''
                        ];
                    }

                    $logpackageNewId = LogPackageModel::insertGetId([
                        'package_id' => $v['package_id'],
                        'package_name' => $package['package_name'],
                        'num' => $v['num'],
                        'sell_price' => $v['price'],
                        'cost' => sprintf('%.6f', self::getPackageCost($v['package_id'])* $v['num']),
                        'out_storage_time' => time(),
                        'all_id_type' => 0,
                        'all_id' => 0,
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'remark' => empty($value['remark'])?'':$value['remark'],
                        'created_at' => time(),
                    ]);

                    foreach ($v['package_content'] as $value){
                        $package_info = PackageContentModel::where(['id' => $value['package_content_id'],'delete_flag' => 0])->first()->toArray();
                        $storageManageInfo = StorageManageModel::where(['id' => $package_info['storage_manage_id']])->first();
                        //查询商品信息
                        $minfo = MaterielsTypeModel::select('is_use_serial')->where('id', $package_info['type_id'])->first();

                        if($minfo['is_use_serial'] == 1 && !empty($value['serial_no'])){//序列号

                        if(!empty($value['serial_no'])){

                        $serial_no_array = explode(',',$value['serial_no']);

                        foreach ($serial_no_array as $k => $serial_data){
                        $value['num'] = 1;
                        if ($v['num']*$value['num'] > $storageManageInfo['in_storage_num']) {
                            return [
                                'code' => 1,
                                'msg' => '套餐可出库数量不足',
                                'data' => ''
                            ];
                        }

                        if ($v['num']*$value['num'] > $storageManageInfo['virtual_storage_num']) {
                            return [
                                'code' => 1,
                                'msg' => '可用库存数不足，无法出库',
                                'data' => ''
                            ];
                        }
                        //检查序列号是否使用
                        $number_info = SerialNumberModel::where(['goods_id' => $storageManageInfo['type_id'],'serial_no' => $serial_data])->first();

                        if(!empty($number_info)){
                            if($number_info['status'] == 0){
                                throw new Exception('该商品：'.$storageManageInfo['materiel_name'].'的序列号：'.$serial_data.'已被使用');
                            }

                        StorageManageModel::where('id', $package_info['storage_manage_id'])
                            ->update([
                                'in_storage_num' => DB::raw('in_storage_num - '.$value['num'] * $v['num']),
                                'virtual_storage_num' => DB::raw('virtual_storage_num - '.$value['num'] * $v['num'])
                            ]);

                        SerialNumberModel::where(['serial_no' => $serial_data,'status' => SerialNumberModel::UNUSEDSTATUS,
                            'goods_id' => $number_info['goods_id'],
                        ])->update(['status' => SerialNumberModel::USEDSTATUS]);

                        LogPackageContentModel::insert([
                            'log_package_id' => $logpackageNewId,
                            'package_id' => $package_info['package_id'],
                            'storage_id' => $storageManageInfo['storage_id'],
                            'storage_name' => $storageManageInfo['storage_name'],
                            'storage_address' => $storageManageInfo['storage_address'],
                            'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                            'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                            'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                            'materiel_type_id' => $storageManageInfo['type_id'],
                            'materiel_name' => $storageManageInfo['materiel_name'],
                            'type_name' => $storageManageInfo['type_name'],
                            'materiel_no' => $storageManageInfo['materiel_no'],
                            'operate_num' => $value['num'] * $v['num'],
                            'out_storage_manage_id' => $storageManageInfo['id'],
                            'last_storage_num' => $storageManageInfo['in_storage_num'],
                            'next_storage_num' => $storageManageInfo['in_storage_num'] - ($value['num'] * $v['num']),
                            'all_id_type' => 4,
                            'all_id' => 0,
                            'user_id' => $data['user_id'],
                            'main_id' => $data['main_id'],
                            'created_at' => time(),
                            'serial_number'=>$serial_data,
                            'shelf_id' =>$storageManageInfo['shelf_id'],
                            'location_id' =>$storageManageInfo['location_id'],

                        ]);
                        }else{
                            return ['code'=>1,'msg'=>'序列号不存在','data'=>''];
                        }
                        }
                        }
                     }else{
                         if(!empty($value['batch_info'])){//批次号

                             foreach ($value['batch_info'] as $bv){
                                 $storageBatchInfo = StorageBatchModel::select(
                                     'a.id',
                                     'b.id as storage_manage_id',
                                     'batch_no',
                                     'batch_left_num',
                                     'b.storage_id',
                                     'c.storage_name',
                                     'c.storage_address',
                                     'b.materiel_mean_cost',
                                     'b.type_id',
                                     'd.materiel_name',
                                     'd.type_name',
                                     'd.materiel_no',
                                     'b.materiel_class_id',
                                     'e.class_name',
                                     'e.class_no',
                                     'in_storage_num',
                                     'alert_num',
                                     'b.shelf_id',
                                     'b.location_id',
                                     'batch_left_num'
                                     )
                                     ->from('storage_batch as a')
                                     ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                                     ->leftJoin('storage as c', 'c.id', '=', 'b.storage_id')
                                     ->leftJoin('materiel_type as d', 'd.id', '=', 'b.type_id')
                                     ->leftJoin('materiel_class as e', 'e.id', '=', 'd.materiel_class_id')
                                     ->where('b.id', $package_info['storage_manage_id'])
                                     ->where('a.id', $bv['batch_id'])
                                     ->where('b.delete_flag', 0);
                                     if($data['is_use_shelf']) {
                                         if(!empty($value['shelf_id']) && !empty($value['location_id'])){
                                             $storageBatchInfo->where('b.shelf_id', $value['shelf_id']);
                                             $storageBatchInfo->where('b.location_id', $value['location_id']);
                                         }
                                     }
                                     $storageBatchInfo = $storageBatchInfo->first();

                                     $value['num'] = $bv['num'];

                                     if(empty($storageBatchInfo)) {

                                         throw new Exception('套餐内商品暂无指定的库存信息，请查验后重试');
                                     }

                                     if($storageBatchInfo['batch_left_num'] < $bv['num']) {
                                         throw new Exception('批次剩余数量不足,无法出库');
                                     }

                                     if($storageBatchInfo['in_storage_num'] < $value['num'] * $v['num']) {
                                         throw new Exception('库存数量不足,无法出库');
                                     }

                                 if($storageBatchInfo['virtual_storage_num'] < $value['num'] * $v['num']) {
                                     throw new Exception('可用库存数不足,无法出库');
                                 }


                                 StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                                     ->update([
                                         'in_storage_num' => DB::raw('in_storage_num - '.$value['num'] * $v['num']),
                                         'virtual_storage_num' => DB::raw('virtual_storage_num - '.$value['num'] * $v['num'])
                                     ]);

                                 StorageBatchModel::where('id', $bv['batch_id'])
                                 ->decrement('batch_left_num', $bv['num']);

                                 LogPackageContentModel::insert([
                                     'log_package_id' => $logpackageNewId,
                                     'package_id' => $package_info['package_id'],
                                     'storage_id' => $storageBatchInfo['storage_id'],
                                     'storage_name' => $storageBatchInfo['storage_name'],
                                     'storage_address' => $storageBatchInfo['storage_address'],
                                     'materiel_class_id' => $storageBatchInfo['materiel_class_id'],
                                     'materiel_class_name' => $storageBatchInfo['materiel_class_name'],
                                     'materiel_class_no' => $storageBatchInfo['materiel_class_no'],
                                     'materiel_type_id' => $storageBatchInfo['type_id'],
                                     'materiel_name' => $storageBatchInfo['materiel_name'],
                                     'type_name' => $storageBatchInfo['type_name'],
                                     'materiel_no' => $storageBatchInfo['materiel_no'],
                                     'operate_num' => $value['num'] * $v['num'],
                                     'out_storage_manage_id' => $storageBatchInfo['id'],
                                     'last_storage_num' => $storageBatchInfo['in_storage_num'],
                                     'next_storage_num' => $storageBatchInfo['in_storage_num'] - ($value['num'] * $v['num']),
                                     'all_id_type' => 4,
                                     'all_id' => 0,
                                     'user_id' => $data['user_id'],
                                     'main_id' => $data['main_id'],
                                     'created_at' => time(),
                                     'storage_batch_id'=>$bv['batch_id'],
                                     'shelf_id' =>$storageBatchInfo['shelf_id'],
                                     'location_id' =>$storageBatchInfo['location_id']
                                 ]);

                             }
                         }else{//没有开通序列号和批次号

                             if ($v['num']*$value['num'] > $storageManageInfo['in_storage_num']) {
                                 return [
                                     'code' => 1,
                                     'msg' => '套餐可出库数量不足',
                                     'data' => ''
                                 ];
                             }
                             if ($v['num']*$value['num'] > $storageManageInfo['virtual_storage_num']) {
                                 return [
                                     'code' => 1,
                                     'msg' => '可用库存数不足，无法出库',
                                     'data' => ''
                                 ];
                             }
                             StorageManageModel::where('id', $package_info['storage_manage_id'])
                                 ->update([
                                     'in_storage_num' => DB::raw('in_storage_num - '.$value['num'] * $v['num']),
                                     'virtual_storage_num' => DB::raw('virtual_storage_num - '.$value['num'] * $v['num'])
                                 ]);

                             LogPackageContentModel::insert([
                                 'log_package_id' => $logpackageNewId,
                                 'package_id' => $package_info['package_id'],
                                 'storage_id' => $storageManageInfo['storage_id'],
                                 'storage_name' => $storageManageInfo['storage_name'],
                                 'storage_address' => $storageManageInfo['storage_address'],
                                 'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                                 'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                                 'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                                 'materiel_type_id' => $storageManageInfo['type_id'],
                                 'materiel_name' => $storageManageInfo['materiel_name'],
                                 'type_name' => $storageManageInfo['type_name'],
                                 'materiel_no' => $storageManageInfo['materiel_no'],
                                 'operate_num' => $value['num'] * $v['num'],
                                 'out_storage_manage_id' => $storageManageInfo['id'],
                                 'last_storage_num' => $storageManageInfo['in_storage_num'],
                                 'next_storage_num' => $storageManageInfo['in_storage_num'] - ($value['num'] * $v['num']),
                                 'all_id_type' => 4,
                                 'all_id' => 0,
                                 'user_id' => $data['user_id'],
                                 'main_id' => $data['main_id'],
                                 'created_at' => time(),
                                 'shelf_id' =>$storageManageInfo['shelf_id'],
                                 'location_id' =>$storageManageInfo['location_id'],

                             ]);
                         }

                     }
                    }
                    DB::commit();
                }
            }catch(Exception $e) {
                DB::rollBack();
                Log::debug('出库'.var_export($e->getMessage(), true));
                return ['code' => 1, 'msg' => '出库失败！', 'data' => ''];

            }
        }
        return ['code' => 0, 'msg' => 'success', 'data' => ''];

    }

    //获取套餐总成本
    static public function getPackageCost($package_id)
    {
        $data = PackageContentModel::select(
            DB::raw('SUM(num * cost) as total_cost')
        )
            ->from('package_content as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
            ->where('a.package_id', $package_id)
            ->groupBy('package_id')
            ->first();

        return $data['total_cost'];
    }

    public static function storeGoods($data, $time)
    {
        if(!empty($data['goods_info'])){
            $goods = json_decode($data['goods_info'],true);

            $serialDataArr = [];
            foreach ($goods as $key => $value){

                //没有传货架库位，使用默认货架库位
                if(empty($data['shelf_id']) || empty($data['location_id'])){
                    $sfData = ShelfService::get_default($data['storage_id']);

                    if(!empty($sfData)){
                    $shelf_id = $sfData['id'];
                    $lData = ShelfService::get_default($shelf_id,2);
                    $location_id = $lData['id'];
                    }else{
                        $shelf_id = 0;
                        $location_id = 0;
                        $data['shelf_id']=0;
                        $data['location_id']=0;
                    }
                }else{
                    $shelf_id = $data['shelf_id'];
                    $location_id = $data['location_id'];
                }

                $materielTypeInfo = MaterielsTypeModel::select(
                    'a.id',
                    'materiel_name',
                    'type_name',
                    'materiel_no',
                    'b.id as materiel_class_id',
                    'b.class_name',
                    'b.class_no',
                    'c.id as first_class',
                    'cost'
                )
                    ->from('materiel_type as a')
                    ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                    ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id')
                    ->where([
                        'materiel_name' => $value['materiel_name'],
                        'type_name' => $value['type_name'],
                        'a.main_id' => $data['main_id'],
                        'a.delete_flag' => 0,
                    ])
                    ->first();

                if(empty($materielTypeInfo)) {
                    throw new Exception('物料`'.$value['materiel_name'].'-'.$value['type_name'].'`不存在');
                }

                //仓库信息
                $storageInfo = StorageModel::where([
                    'storage_name' => $data['storage_name'],
                    'id' => $data['storage_id'],
                    'main_id' => $data['main_id'],
                    'delete_flag' => 0,
                ])->first();

                if(empty($storageInfo)) {
                    throw new Exception('仓库`'.$data['storage_name'].'`不存在');

                }

                //检查库存信息
                $checkStorageManage = StorageManageModel::where([
                    'type_id' => $materielTypeInfo['id'],
                    'storage_id' => $data['storage_id'],
                    'main_id' => $data['main_id'],
                    'delete_flag' => 0,
                ])->first();

                $minfo = MaterielsTypeModel::select('is_use_serial')->where('id',$materielTypeInfo['id'])->first();
                $serialData = [];
                if($minfo['is_use_serial'] == 1){
                    if(empty($value['serial_no'])) {
                        throw new Exception('商品:'.$materielTypeInfo['materiel_name'].'已开启序列号选项，请填写序列号');
                    }

                    $serialData = array_filter(explode(',', $value['serial_no']), function($v) { return $v !== ''; });

                    if($value['num'] != count($serialData)) {
                        throw new Exception('序列号个数与入库数量不符');
                    }

                    $checkSerialInfo = SerialNumberModel::where('goods_id', $materielTypeInfo['id'])
                        ->whereIn('serial_no', $serialData)
                        ->first();

                    if(!empty($checkSerialInfo)) {
                        throw new Exception('商品:'.$materielTypeInfo['materiel_name'].'中序列号:'.$checkSerialInfo['serial_no'].'已存在');
                    }
                }

                $newStorageManageInfo = [];//新物料入库
                $updateInStorageNum = [];//已有物料入库
                if(empty($checkStorageManage)) {
                    $newStorageManageInfo = [
                        'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类id
                        'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
                        'materiel_class_no' => empty($materielTypeInfo['class_no'])?'':$materielTypeInfo['class_no'],//物料二级分类名称
                        'type_id' => $materielTypeInfo['id'],//物料id
                        'materiel_name' => $materielTypeInfo['materiel_name'],//物料名称
                        'type_name' => $materielTypeInfo['type_name'],//物料型号名称
                        'materiel_no' => empty($materielTypeInfo['materiel_no'])?'':$materielTypeInfo['materiel_no'],//物料编号
                        'materiel_mean_cost' => $materielTypeInfo['cost'] == 0?0:$materielTypeInfo['cost'],
                        'storage_id' => $storageInfo['id'],//仓库id
                        'storage_name' => $storageInfo['storage_name'],//仓库名
                        'storage_address' => $storageInfo['storage_address'],//仓库地址
                        'in_storage_num' => $value['num'],//采购单内物料商品入库数量
                        'virtual_storage_num' => $value['num'],
                        'main_id' => $data['main_id'],//主账号id
                        'in_storage_time' => $time,//入库时间
                        'alert_num' => $data['alert_num'],
                        'created_at' => $time,

                        'shelf_id' => $shelf_id,
                        'location_id' => $location_id,
                    ];

//                    MessageService::sendInSms(
//                        '无',
//                        $materielTypeInfo['materiel_name'],
//                        $materielTypeInfo['type_name'],
//                        $storageInfo['id'],
//                        $storageInfo['storage_name'],
//                        $data,
//                        $value['num'],
//                        $value['num']
//                    );
                }
                else {
                    $updateInStorageNum = [
                        'id' => $checkStorageManage->id,
                        'in_storage_num' => $value['num'],
                        'alert_num' => $data['alert_num'],
                        'remark' => $data['remark'],
                        'materiel_mean_cost' => $materielTypeInfo['cost'],
                    ];
//
//                    MessageService::sendInSms(
//                        '无',
//                        $materielTypeInfo['materiel_name'],
//                        $materielTypeInfo['type_name'],
//                        $storageInfo['id'],
//                        $storageInfo['storage_name'],
//                        $data,
//                        $value['num'],
//                        $checkStorageManage['in_storage_num'] + $value['num']
//                    );
                }

                $inStorageNum = !empty($checkStorageManage)?$checkStorageManage['in_storage_num']:0;

                //入库操作记录
                $logInStorage = [
                    'type' => 2,//日志类型;0:入库;1:调拨入库;2:直接入库;
                    'storage_id' => $storageInfo['id'],//入库目标仓库id
                    'storage_name' => $storageInfo['storage_name'],//仓库名
                    'storage_address' => $storageInfo['storage_address'],//仓库地址
                    'last_storage_id' => 0,//调拨前所在仓库id
                    'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类id
                    'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
                    'materiel_class_no' => empty($materielTypeInfo['class_no'])?'':$materielTypeInfo['class_no'],//物料二级分类名称
                    'materiel_type_id' => $materielTypeInfo['id'],//物料id
                    'materiel_name' => $materielTypeInfo['materiel_name'],//物料名称
                    'type_name' => $materielTypeInfo['type_name'],//物料型号名称
                    'materiel_no' => empty($materielTypeInfo['materiel_no'])?'':$materielTypeInfo['materiel_no'],//物料编号
                    'operate_num' => $value['num'],//操作数量
                    'last_storage_num' => $inStorageNum,//操作前库存数
                    'next_storage_num' => $inStorageNum + $value['num'],//操作后库存数
                    'materiel_mean_cost' => 0,//物料均价
                    'in_storage_time' => $time,//入库时间
                    'remark' => $data['remark'],//备注
                    'all_id_type' => 0,//单据类型;0:无;1:报溢;2:报损;3:采购;
                    'all_id' => 0,//单据id
                    'user_id' => $data['user_id'],//操作人id
                    'main_id' => $data['main_id'],//主账号id
                    'created_at' => $time,
                    'serial_number'=>!empty($value['serial_no'])?$value['serial_no']:'',
                    'shelf_id' => $shelf_id,
                    'location_id' => $location_id,
                ];

                $meanCost = 0;
                if(!empty($newStorageManageInfo)) {
                    $meanCost = $newStorageManageInfo['materiel_mean_cost'];
                    $newStorageManageId = StorageManageModel::insertGetId($newStorageManageInfo);
                }

                if(!empty($updateInStorageNum)) {
                    StorageManageModel::where('id', $updateInStorageNum['id'])
                        ->update([
                            'in_storage_num' => DB::raw('in_storage_num + '.$value['num']),
                            'virtual_storage_num' => DB::raw('virtual_storage_num + '.$value['num']),
                            'alert_num' => $data['alert_num'],
                            'materiel_mean_cost' => $updateInStorageNum['materiel_mean_cost'],
                        ]);

                    $meanCost =  $updateInStorageNum['materiel_mean_cost'];
                    $newStorageManageId = $updateInStorageNum['id'];
                }

                $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(1000, 9999).'0';

                do{
                    $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(1000, 9999).'0';
                }
                while(!empty(StorageBatchModel::where('batch_no', $batchNo)->first()));

                StorageBatchModel::insert([
                    'batch_no' => $batchNo,
                    'storage_manage_id' => $newStorageManageId,
                    'batch_num' => $value['num'],
                    'batch_left_num' => $value['num'],
                    'batch_cost' => $meanCost,
                    'materiel_id' => 0,
                    'main_id' => $data['main_id'],
                    'created_at' => $time
                ]);

                $logInStorage['curr_storage_manage_id'] = $newStorageManageId;

                LogInstorageModel::insert($logInStorage);

                if(!empty($serialData)) {
                    foreach($serialData as $serialValue) {
                        $serialDataArr[] = [
                            'serial_no' => $serialValue,
                            'batch_no' => $batchNo,
                            'storage_manage_id' => $newStorageManageId,
                            'goods_id' => $materielTypeInfo['id'],
                            'created_at' =>  $time,
                            'main_id'=> $data['main_id']
                        ];
                    }
                }
            }

            if(!empty($serialDataArr)) {
                SerialNumberModel::insert($serialDataArr);
            }
        }

        return true;
    }

    static public function oneKeyClear($data)
    {
        //比对用户输入的code和短信发送的code是否一致
        if(!Redis::exists($data['mobile'].'_one_clear')) {
            return ['code' => 1, 'msg' => '您输入的验证码无效，请重试', 'data' => ''];
        }
        else {
            if($data['code'] == Redis::get($data['mobile'].'_one_clear')) {//验证码一致
                $checkStorage = StorageManageModel::where([
                    'delete_flag' => 0,
                    'main_id' => $data['main_id']
                ])
                    ->first();

                $checkMateriel = MaterielsTypeModel::where([
                    'delete_flag' => 0,
                    'main_id' => $data['main_id']
                ])
                    ->first();

                $checkClass = MaterielClassModel::where([
                    'delete_flag' => 0,
                    'main_id' => $data['main_id']
                ])
                    ->first();

                DB::beginTransaction();

                try {
                    if(!empty($data['clear_finance'])) {
                        if($data['clear_finance'] == 1) {
                            OverflowBreakageModel::where('main_id', $data['main_id'])
                                ->update(['delete_flag' => 1]);

                            SalesReturnModel::where('main_id', $data['main_id'])
                                ->update(['delete_flag' => 1]);

                            SellModel::where('main_id', $data['main_id'])
                                ->update(['delete_flag' => 1]);

                            MaterielModel::where('main_id', $data['main_id'])
                                ->update(['delete_flag' => 1]);

                            ProductOrderModel::where('main_id', $data['main_id'])
                                ->update(['delete_flag' => 1]);

                            TallyModel::where('main_id', $data['main_id'])
                                ->update(['delete_flag' => 1]);
                        }
                    }

                    //清除库存
                    if($data['clear_storage']) {
                        if(!empty($checkStorage)) {
                            self::clearStorage($data);
                        }
                    }

                    if($data['clear_materiel']) {
                        if(!empty($checkStorage)) {
                            self::clearStorage($data);
                        }
                        if(!empty($checkMateriel)) {
                            self::clearMateriel($data);
                        }
                    }

                    if($data['clear_class']) {
                        if(!empty($checkStorage)) {
                            self::clearStorage($data);
                        }
                        if(!empty($checkMateriel)) {
                            self::clearMateriel($data);
                        }
                        if(!empty($checkClass)) {
                            self::clearClass($data);
                        }
                    }

                    if(isset($data['clear_log'])) {
                        self::clearLog($data);
                    }

                    DB::commit();
                    Redis::del($data['mobile'].'_one_clear');//一键清除后销毁验证码
                    return ['code' => 0, 'msg' => 'success', 'data' => ''];
                }
                catch(Exception $e) {
                    DB::rollBack();
                    var_dump($e->getMessage());
                    Log::debug('一键清除异常:'.var_export($data, true));
                    return ['code' => 1, 'msg' => '一键清除失败！', 'data' => ''];
                }
            }else {
                return ['code' => 1, 'msg' => '您输入的验证码有误，请重新输入', 'data' => ''];
            }
        }
    }

    //一键清除库存
    static private function clearStorage($data)
    {
            $list = StorageManageModel::select('id')
                    ->where(['delete_flag' => 0,'main_id' => $data['main_id']])->get()->toArray();
            if(!empty($list)){
              foreach($list as $val){
                  SerialNumberModel::where(['storage_manage_id'=>$val['id']])->delete();
              }
            }
            StorageManageModel::where([
                'delete_flag' => 0,
                'main_id' => $data['main_id']
            ])
                ->update([
                    'in_storage_num' => 0,
                    'virtual_storage_num' => 0,
                    'delete_flag' => 1
                ]);

            return true;
    }

    //一键清除商品信息
    static private function clearMateriel($data)
    {
        MaterielsTypeModel::where([
            'delete_flag' => 0,
            'main_id' => $data['main_id']
        ])
            ->update(['delete_flag' => 1]);

        return true;
    }

    static private function clearClass($data)
    {
        MaterielClassModel::where([
            'delete_flag' => 0,
            'main_id' => $data['main_id']
        ])
            ->update(['delete_flag' => 1]);

        return true;
    }

    static public function storageManageIn($data)
    {
        $storageManageInfo = StorageManageModel::select(
            'a.id',
            'a.type_id',
            'in_storage_num',
            'virtual_storage_num',
            'materiel_mean_cost',
            'b.type_name',
            'b.materiel_name',
            'b.materiel_no',
            'a.materiel_class_id',
            'c.class_name',
            'c.class_no',
            'a.storage_id',
            'd.storage_name',
            'd.storage_address',
            'shelf_id',
            'location_id'
        )
            ->from('storage_manage as a')
            ->leftJoin('materiel_type as b', 'a.type_id', '=', 'b.id')
            ->leftJoin('materiel_class as c', 'c.id', '=', 'a.materiel_class_id')
            ->leftJoin('storage as d', 'd.id', '=', 'a.storage_id')
            ->where('a.id', $data['id'])->first();

        DB::beginTransaction();

        try {
            StorageManageModel::where('id', $data['id'])
                ->update([
                    'in_storage_num' => DB::raw('in_storage_num + '.$data['num']),
                    'virtual_storage_num' => DB::raw('virtual_storage_num + '.$data['num'])
                ]);

            $batchNo = $data['batch_title'].date('YmdHis', time()).mt_rand(1000, 9999).'0';
            $checkBatchNo = StorageBatchModel::where('main_id', $data['main_id'])
                ->where('batch_no', $batchNo)->first();

            do {
                $batchNo = $data['batch_title'].date('YmdHis', time()).mt_rand(1000, 9999).'0';
            }
            while(!empty($checkBatchNo));

            $batchId = MaterielService::createBatchInfoGetId(
                $batchNo,
                $storageManageInfo['id'],
                $storageManageInfo['materiel_mean_cost'],
                $storageManageInfo['in_storage_num'],
                0,
                $data['main_id']
            );

            LogInstorageModel::insert([
                'curr_storage_manage_id' => $storageManageInfo['id'],
                'materiel_type_id' => $storageManageInfo['type_id'],//物料id
                'batch_id' => $batchId,//物料id
                'materiel_name' => $storageManageInfo['materiel_name'],//物料名称
                'type_name' => $storageManageInfo['type_name'],//物料型号
                'materiel_no' => $storageManageInfo['materiel_no'],//物料编号
                'materiel_class_id' => $storageManageInfo['materiel_class_id'],//物料二级分类主键名称
                'materiel_class_name' => $storageManageInfo['class_name'],//物料二级分类名称
                'materiel_class_no' => $storageManageInfo['class_no'],//物料二级分类编号
                'type' => 2,//入库日志类型;0:入库;1:调拨入库;2:直接入库;
                'storage_id' => $storageManageInfo['storage_id'],//仓库主键id
                'storage_name' => $storageManageInfo['storage_name'],//仓库名
                'storage_address' => $storageManageInfo['storage_address'],//仓库地址
                'last_storage_id' => 0,//调拨前所在仓库id
                'operate_num' => $data['num'],//操作数量
                'last_storage_num' => 0,//操作前库存数
                'materiel_mean_cost' => empty($storageManageInfo)?0:$storageManageInfo['materiel_mean_cost'],//物料均价
                'next_storage_num' => $storageManageInfo['in_storage_num']+$data['num'],//操作后库存数
                'all_id_type' => 0,//单据类型;0:无;1:报溢;2:退货;3:采购;
                'in_storage_time' => time(),//入库时间
                'shelf_id' => $storageManageInfo['id'],
                'location_id' => $storageManageInfo['id'],
                'all_id' => 0,//单据id
                'user_id' => $data['user_id'],//操作人用户id
                'main_id' => $data['main_id'],//主账号id
                'remark' => empty($data['remark'])?'':$data['remark'],
                'label_name' => !empty($data['label_name'])?$data['label_name']:"",
                'created_at' => time(),
            ]);

            MessageService::sendInSms(
                time(),
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['storage_id'],
                $storageManageInfo['storage_name'],
                $data,
                $data['num'],
                $storageManageInfo['in_storage_num'] + $data['num']
                );
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('库存直接入库异常:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '直接入库失败！', 'data' => ''];
        }
    }

    //直接入库(新建入库)
    static public function directInStorage($data)
    {
        $data['alert_num'] = $data['status'] == 1?$data['alert_num']:0;
        $data['remark'] = empty($data['remark'])?'':$data['remark'];

        $materielTypeInfo = MaterielTypeModel::select(
            'a.id',
            'materiel_name',
            'type_name',
            'materiel_no',
            'b.id as materiel_class_id',
            'b.class_name',
            'b.class_no',
            'c.id as first_class',
            'cost'
        )
            ->from('materiel_type as a')
            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
            ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id')
            ->where([
                'materiel_name' => $data['materiel_name'],
                'type_name' => $data['type_name'],
                'a.main_id' => $data['main_id'],
                'a.delete_flag' => 0,
            ])
            ->first();

        if(empty($materielTypeInfo)) {
            return ['code' => 1, 'msg' => '物料`'.$data['materiel_name'].'-'.$data['type_name'].'`不存在', 'data' => ''];
        }

        //仓库信息
        $storageInfo = StorageModel::where([
            'storage_name' => $data['storage_name'],
            'id' => $data['storage_id'],
            'main_id' => $data['main_id'],
            'delete_flag' => 0,
        ])->first();

        if(empty($storageInfo)) {
            return ['code' => 1, 'msg' => '仓库`'.$data['storage_name'].'`不存在', 'data' => ''];
        }

        //检查库存信息
        $checkStorageManage = StorageManageModel::where([
            'type_id' => $materielTypeInfo['id'],
            'storage_id' => $data['storage_id'],
            'main_id' => $data['main_id'],
        ])->first();

        $newStorageManageInfo = [];//新物料入库
        $updateInStorageNum = [];//已有物料入库
        if(empty($checkStorageManage)) {
            $newStorageManageInfo = [
                'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类id
                'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
                'materiel_class_no' => empty($materielTypeInfo['class_no'])?'':$materielTypeInfo['class_no'],//物料二级分类名称
                'type_id' => $materielTypeInfo['id'],//物料id
                'materiel_name' => $materielTypeInfo['materiel_name'],//物料名称
                'type_name' => $materielTypeInfo['type_name'],//物料型号名称
                'materiel_no' => empty($materielTypeInfo['materiel_no'])?'':$materielTypeInfo['materiel_no'],//物料编号
                'materiel_mean_cost' => $materielTypeInfo['cost'] == 0?0:$materielTypeInfo['cost'],
                'storage_id' => $storageInfo['id'],//仓库id
                'storage_name' => $storageInfo['storage_name'],//仓库名
                'storage_address' => $storageInfo['storage_address'],//仓库地址
                'in_storage_num' => $data['num'],//采购单内物料商品入库数量
                'virtual_storage_num' => $data['num'],
                'main_id' => $data['main_id'],//主账号id
                'in_storage_time' => time(),//入库时间
                'alert_num' => $data['alert_num'],
                'created_at' => time(),
            ];

            MessageService::sendInSms(
                '无',
                $materielTypeInfo['materiel_name'],
                $materielTypeInfo['type_name'],
                $storageInfo['id'],
                $storageInfo['storage_name'],
                $data,
                $data['num'],
               $data['num'],
            );
        }
        else {
            $updateInStorageNum = [
                'id' => $checkStorageManage->id,
                'in_storage_num' => $data['num'],
                'alert_num' => $data['alert_num'],
                'remark' => $data['remark'],
                'materiel_mean_cost' => $materielTypeInfo['cost'],
            ];

            MessageService::sendInSms(
                '无',
                $materielTypeInfo['materiel_name'],
                $materielTypeInfo['type_name'],
                $storageInfo['id'],
                $storageInfo['storage_name'],
                $data,
                $data['num'],
                $checkStorageManage['in_storage_num'] + $data['num'],
            );
        }

        $inStorageNum = !empty($checkStorageManage)?$checkStorageManage['in_storage_num']:0;

        //入库操作记录
        $logInStorage = [
            'type' => 2,//日志类型;0:入库;1:调拨入库;2:直接入库;
            'storage_id' => $storageInfo['id'],//入库目标仓库id
            'storage_name' => $storageInfo['storage_name'],//仓库名
            'storage_address' => $storageInfo['storage_address'],//仓库地址
            'last_storage_id' => 0,//调拨前所在仓库id
            'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类id
            'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
            'materiel_class_no' => empty($materielTypeInfo['class_no'])?'':$materielTypeInfo['class_no'],//物料二级分类名称
            'materiel_type_id' => $materielTypeInfo['id'],//物料id
            'materiel_name' => $materielTypeInfo['materiel_name'],//物料名称
            'type_name' => $materielTypeInfo['type_name'],//物料型号名称
            'materiel_no' => empty($materielTypeInfo['materiel_no'])?'':$materielTypeInfo['materiel_no'],//物料编号
            'operate_num' => $data['num'],//操作数量
            'last_storage_num' => $inStorageNum,//操作前库存数
            'next_storage_num' => $inStorageNum + $data['num'],//操作后库存数
            'materiel_mean_cost' => 0,//物料均价
            'in_storage_time' => time(),//入库时间
            'remark' => $data['remark'],//备注
            'all_id_type' => 0,//单据类型;0:无;1:报溢;2:报损;3:采购;
            'all_id' => 0,//单据id
            'user_id' => $data['user_id'],//操作人id
            'main_id' => $data['main_id'],//主账号id
            'created_at' => time()
        ];

        DB::beginTransaction();

        try {
            $meanCost = 0;
            if(!empty($newStorageManageInfo)) {
                $meanCost = $newStorageManageInfo['materiel_mean_cost'];
                $newStorageManageId = StorageManageModel::insertGetId($newStorageManageInfo);
            }

            if(!empty($updateInStorageNum)) {
                StorageManageModel::where('id', $updateInStorageNum['id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num + '.$data['num']),
                        'virtual_storage_num' => DB::raw('virtual_storage_num + '.$data['num']),
                        'alert_num' => $data['alert_num'],
                        'materiel_mean_cost' => $updateInStorageNum['materiel_mean_cost'],
                        'delete_flag' => 0
                    ]);

                $meanCost =  $updateInStorageNum['materiel_mean_cost'];
                $newStorageManageId = $updateInStorageNum['id'];
            }

            $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(1000, 9999).'0';
            $checkBatchInfo = StorageBatchModel::where('batch_no', $batchNo)->first();

            do{
                $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(1000, 9999).'0';
            }
            while(!empty($checkBatchInfo));

            StorageBatchModel::insert([
                'batch_no' => $batchNo,
                'storage_manage_id' => $newStorageManageId,
                'batch_num' => $data['num'],
                'batch_left_num' => $data['num'],
                'batch_cost' => $meanCost,
                'materiel_id' => 0,
                'main_id' => $data['main_id'],
                'created_at' => time()
            ]);

            $logInStorage['curr_storage_manage_id'] = $newStorageManageId;

            LogInstorageModel::insert($logInStorage);

            MessageService::sendInSms(
                '无',
                $materielTypeInfo['materiel_name'],
                $materielTypeInfo['type_name'],
                $storageInfo['id'],
                $storageInfo['storage_name'],
                $data,
                1,
                $inStorageNum+ 1,
            );
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch (Exception $e) {
            DB::rollback();
            Log::debug('新建入库(直接入库：'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => "直接入库失败！", 'data' => ''];
        }
    }

    //扫码入库
    public static function scanCodesInStorage($data){
        $goodsId = "";
        $barCode = "";
        $serialNumber = "";
        $clickflag = 0;
        $remark  ="";
        $number = "";
        switch ($data['code_type']) {
            case 0://物料商品id
                if(strpos($data['batch_no'], 'smycg')!==false){//物料商品id
                    $data['batch_no'] = substr($data['batch_no'],5,strlen($data['batch_no'])-1);
                    $goodsId = $data['batch_no'];
                    $remark  = "商品ID";
                }
            break;
            case 1://序列号
                if(!empty($data['goods_id']) && !empty($data['batch_no'])){
                    $goodsId = $data['goods_id'];
                    $serialNumber = $data['batch_no'];
                    $remark  = "序列号";
                    if(!empty($data['click_flag'])){
                        $clickflag = $data['click_flag'];
                    }
                }
            break;
            case 2://批次号
                return ['code'=>1,'msg'=>'批次号出库，正在维护中！','data'=>''];
                /*if($batchSign.'0' == $data['batch_title'].$batchNoTag) {//商品批次號
                    $result = ['code'=>1,'msg'=>'批次号出库，正在维护中！','data'=>''];
                    $remark  = "批次号";
                }*/
            break;
            case 3://条形码
                if(!empty($data['batch_no'])){
                    $mInfo = MaterielTypeModel::where([
                            'main_id'     => $data['main_id'],
                            'delete_flag' => 0,
                            'bar_code'    =>$data['batch_no']
                            ])->first();

                    if(empty($mInfo)){
                        $mList = MaterielTypeModel::where([
                            'main_id'   => $data['main_id'],
                            'delete_flag' => 0
                        ])->where('number_prefix','!=','')->get()->toArray();

                        if(!empty($mList)){
                            foreach ($mList as $val){
                                if(strpos($data['batch_no'], $val['number_prefix']) !== false){
                                    $goodsId = $val['id'];
                                }
                            }
                        }
                    }

                    if(empty($goodsId)){
                        $barCode = $data['batch_no'];
                    }
                    $remark  = "条形码";
                }
                break;
            default:
                if(!empty($data['batch_no'])){
                    $number = $data['batch_no'];//外部编号
                    $mList = MaterielTypeModel::where([
                        'a.main_id'   => $data['main_id'],
                        'delete_flag' => 0
                    ])->where('number_prefix','!=','')->get();
                    if(!empty($mList)){
                        foreach ($mList as $val){
                            if(strpos($number, $val['number_prefix']) !== false){
                                $goodsId = $val['id'];
                            }
                        }
                    }
                    if(empty($goodsId)){
                        return ['code'=>1,'msg'=>'编码商品信息,不存在!','data'=>''];
                    }
                    $remark = "编号码";
                }
            break;
        }

        $materielTypeInfo = MaterielsTypeModel::select(
            'a.id',
            'materiel_name',
            'type_name',
            'materiel_no',
            'b.id as materiel_class_id',
            'b.class_name',
            'b.class_no',
            'c.id as first_class',
            'cost',
            'a.is_use_serial',
            'a.is_product_materiel'
            )
            ->from('materiel_type as a')
            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
            ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id');
            if(!empty($goodsId)){
                $materielTypeInfo->where('a.id',$goodsId);
            }
            if(!empty($barCode)){
                $materielTypeInfo->where('a.bar_code',$barCode);
            }
        $materielTypeInfo = $materielTypeInfo->where([
            'a.main_id'=>$data['main_id'],
            'a.delete_flag'=>0,
            'b.delete_flag'=>0
        ])->first();

            if(empty($materielTypeInfo)) {
                    return ['code'=>1,'msg'=>'物料'.$remark.'信息,不存在!','data'=>''];
            }

        if (!empty($materielTypeInfo)) {
            if ($materielTypeInfo['is_product_materiel'] == 1) {//是套餐
                $pCondition = ['product_id' => $materielTypeInfo['id']];
                if (!empty($materielTypeInfo['is_use_serial'])) {
                    return ['code' => 1, 'msg' => '套餐商品已开启序列号，请使用快速出库操作', 'data' => ''];
                }
            } else {//套餐里的商品
                $pInfo = MaterielProductContentModel::where([
                    'main_id'=>$data['main_id'],
                    'type_id' => $materielTypeInfo['id'],
                    'delete_flag' => 0
                ])->first();

                if (!empty($pInfo['product_id'])) {
                    $pCondition = ['product_id' => $pInfo['product_id']];
                }
            }
            if (!empty($pCondition['product_id'])) {
                $pList = MaterielProductContentModel::where($pCondition)->where('delete_flag', 0)->get();
                if (!empty($pList)) {
                    foreach ($pList as $pVal) {
                        $pInfo = MaterielTypeModel::where(['id' => $pVal['type_id']])
                            ->where(['main_id' => $data['main_id'], 'delete_flag' => 0])->first();
                        if (!empty($pInfo['is_use_serial'])) {
                            return ['code' => 1, 'msg' => '套餐商品已开启序列号，请使用快速出库操作', 'data' => ''];
                        }
                    }
                }
            }
        }
        //仓库信息
        $storageInfo = StorageModel::where([
            'id' => $data['storage_id'],
            'main_id' => $data['main_id'],
            'delete_flag' => 0,
        ])->first();

        if(empty($storageInfo)) {
            return ['code'=>1,'msg'=>'你选择的仓库，不存在！','data'=>''];
        }

        //检查库存信息
        $checkStorageManage = StorageManageModel::where([
            'type_id' => $materielTypeInfo['id'],
            'storage_id' => $data['storage_id'],
            'main_id' => $data['main_id'],
            'delete_flag'=>0
        ])->first();

        if($materielTypeInfo['is_use_serial'] == 1){
            if(empty($serialNumber)) {
                    return ['code'=>1,'msg'=>'商品'.$materielTypeInfo['materiel_name'].'已开启序列号选项，请选择序列号入库','data'=>''];
            }

            $checkSerialInfo = SerialNumberModel::where('goods_id', $materielTypeInfo['id'])
                ->where('serial_no', $serialNumber)->first();

            if(!empty($checkSerialInfo)) {
                if($checkSerialInfo['status'] == 0){
                    if(empty($clickflag)){
                    return ['code'=>101,'msg'=>'商品'.$materielTypeInfo['materiel_name'].'中序列号:'.$checkSerialInfo['serial_no'].'已被使用是否再次入库？','data'=>''];
                    }
                }else{
                    return ['code'=>1,'msg'=>'商品'.$materielTypeInfo['materiel_name'].'中序列号:'.$checkSerialInfo['serial_no'].'已存在','data'=>''];
                }
            }
        }

        $newStorageManageInfo = [];//新物料入库
        $updateInStorageNum = [];//已有物料入库
        if(empty($checkStorageManage)) {

            $sfData = ShelfService::get_default($data['storage_id']);
            $shelf_id = 0;
            $location_id = 0;

            if(!empty($sfData)){
                $shelf_id = $sfData['id'];
                $lData = ShelfService::get_default($shelf_id,2);
                $location_id = $lData['id'];
            }

            $newStorageManageInfo = [
                'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类id
                'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
                'materiel_class_no' => empty($materielTypeInfo['class_no'])?'':$materielTypeInfo['class_no'],//物料二级分类名称
                'type_id' => $materielTypeInfo['id'],//物料id
                'materiel_name' => $materielTypeInfo['materiel_name'],//物料名称
                'type_name' => $materielTypeInfo['type_name'],//物料型号名称
                'materiel_no' => empty($materielTypeInfo['materiel_no'])?'':$materielTypeInfo['materiel_no'],//物料编号
                'materiel_mean_cost' => $materielTypeInfo['cost'] == 0?0:$materielTypeInfo['cost'],
                'storage_id' => $storageInfo['id'],//仓库id
                'storage_name' => $storageInfo['storage_name'],//仓库名
                'storage_address' => $storageInfo['storage_address'],//仓库地址
                'in_storage_num' =>1,//采购单内物料商品入库数量
                'virtual_storage_num' => 1,
                'main_id' => $data['main_id'],//主账号id
                'in_storage_time' => $data['time'],//入库时间
                'alert_num' => 0,
                'created_at' => $data['time'],
                'shelf_id' => $shelf_id,
                'location_id' => $location_id,
            ];
        } else {
            $updateInStorageNum = [
                'id' => $checkStorageManage->id,
                'in_storage_num' => 1,
                'materiel_mean_cost' => $materielTypeInfo['cost'],
            ];

            $shelf_id = $checkStorageManage['shelf_id'];
            $location_id = $checkStorageManage['location_id'];
        }
        $sortFlag = 0;
        $inStorageNum = !empty($checkStorageManage)?$checkStorageManage['in_storage_num']:0;
            if(!empty($checkStorageManage['alert_num'])) {
                if ($inStorageNum + 1 > $checkStorageManage['alert_num']) {
                    $sortFlag = 0;
                }else{
                    $sortFlag=1;
                }
            }
        //入库操作记录
        $logInStorage = [
            'type' => 3,//日志类型;0:入库;1:调拨入库;2:直接入库;3扫码入库
            'storage_id' => $storageInfo['id'],//入库目标仓库id
            'storage_name' => $storageInfo['storage_name'],//仓库名
            'storage_address' => $storageInfo['storage_address'],//仓库地址
            'last_storage_id' => 0,//调拨前所在仓库id
            'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类id
            'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
            'materiel_class_no' => empty($materielTypeInfo['class_no'])?'':$materielTypeInfo['class_no'],//物料二级分类名称
            'materiel_type_id' => $materielTypeInfo['id'],//物料id
            'materiel_name' => $materielTypeInfo['materiel_name'],//物料名称
            'type_name' => $materielTypeInfo['type_name'],//物料型号名称
            'materiel_no' => empty($materielTypeInfo['materiel_no'])?'':$materielTypeInfo['materiel_no'],//物料编号
            'operate_num' => 1,//操作数量
            'last_storage_num' => $inStorageNum,//操作前库存数
            'next_storage_num' => $inStorageNum + 1,//操作后库存数
            'materiel_mean_cost' => 0,//物料均价
            'in_storage_time' => $data['time'],//入库时间
            'remark' => "",//备注
            'all_id_type' => 0,//单据类型;0:无;1:报溢;2:报损;3:采购;
            'all_id' => 0,//单据id
            'user_id' => $data['user_id'],//操作人id
            'main_id' => $data['main_id'],//主账号id
            'created_at' => $data['time'],
            'serial_number'=>!empty($serialNumber)?$serialNumber:'',
            'shelf_id' => $shelf_id,
            'location_id' => $location_id
        ];

        DB::beginTransaction();
        try {
            $meanCost = 0;
            if(!empty($newStorageManageInfo)) {
                $meanCost = $newStorageManageInfo['materiel_mean_cost'];
                $newStorageManageId = StorageManageModel::insertGetId($newStorageManageInfo);
            }

            if(!empty($updateInStorageNum)) {
                StorageManageModel::where('id', $updateInStorageNum['id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num + 1'),
                        'virtual_storage_num' => DB::raw('virtual_storage_num + 1'),
                        'materiel_mean_cost' => $updateInStorageNum['materiel_mean_cost'],
                        'sort_flag'=>$sortFlag
                    ]);

                $meanCost =  $updateInStorageNum['materiel_mean_cost'];
                $newStorageManageId = $updateInStorageNum['id'];
            }

            $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(1000, 9999).'0';

            do{
                $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(1000, 9999).'0';
            }
            while(!empty(StorageBatchModel::where('batch_no', $batchNo)->first()));

                StorageBatchModel::insert([
                    'batch_no' => $batchNo,
                    'storage_manage_id' => $newStorageManageId,
                    'batch_num' => 1,
                    'batch_left_num' => 1,
                    'batch_cost' => $meanCost,
                    'materiel_id' => 0,
                    'main_id' => $data['main_id'],
                    'created_at' => $data['time']
                ]);

            $logInStorage['curr_storage_manage_id'] = $newStorageManageId;

            LogInstorageModel::insert($logInStorage);
            if(!empty($serialNumber)){
                if(!empty($clickflag)){
                    SerialNumberModel::where(['goods_id'=>$materielTypeInfo['id'],'serial_no'=>$serialNumber])->update(['status'=>1]);
                }else {
                  SerialNumberModel::insert([
                      'serial_no' => $serialNumber,
                      'batch_no' => $batchNo,
                      'storage_manage_id' => $newStorageManageId,
                      'goods_id' => $materielTypeInfo['id'],
                      'created_at' => $data['time'],
                      'main_id' => $data['main_id']
                  ]);
                }
            }
            MessageService::sendInSms(
                '无',
                $materielTypeInfo['materiel_name'],
                $materielTypeInfo['type_name'],
                $storageInfo['id'],
                $storageInfo['storage_name'],
                $data,
                $inStorageNum,
                $inStorageNum+1
            );
            CommonService::operateResult($data['user_id'],$newStorageManageId,$data['time']);
            DB::commit();
            return ['code'=>0,'msg'=>'success','data'=>''];
        } catch (\Exception $e) {
            DB::rollBack();
            Log::debug($remark.'扫码入库'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $remark.'扫码，入库失败！', 'data' => ''];
        }
    }
    //直接出库
    static public function directOutStorage($data)
    {
        //需出库物料信息
        $storageManageInfo = StorageManageModel::select(
            'a.id',
            'a.storage_id',
            'a.materiel_class_id',
            'a.type_id',
            'a.in_storage_num',
            'a.materiel_mean_cost',
            'b.class_name as materiel_class_name',
            'b.class_no as materiel_class_no',
            'c.materiel_name',
            'c.type_name',
            'c.materiel_no',
            'd.storage_name',
            'd.storage_address',
            'a.alert_num',
            'a.virtual_storage_num',
        )
            ->from('storage_manage as a')
            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
            ->leftJoin('materiel_type as c', 'c.id', '=', 'a.type_id')
            ->leftJoin('storage as d', 'd.id', '=', 'a.storage_id')
            ->where([
                'a.id' => $data['id'],
                'a.main_id' => $data['main_id'],
                'a.delete_flag' => 0
            ])->first();

        if(empty($storageManageInfo)) {
            return ['code' => 1, 'msg' => '库存中不存在的物料，无法出库', 'data' => ''];
        }

        if($storageManageInfo['in_storage_num'] < $data['num']) {
            return ['code' => 1, 'msg' => '操作数量超出实际库存数，无法完成出库,当前库存数为:'.$storageManageInfo['in_storage_num'], 'data' => ''];
        }

        DB::beginTransaction();

        try {
            //出库操作记录日志
            LogOutstorageModel::insert([
                'type' => 2,//type;0:出库;1:调出;2:直接出库;
                'storage_id' => $storageManageInfo['storage_id'],
                'storage_name' => $storageManageInfo['storage_name'],
                'storage_address' => $storageManageInfo['storage_address'],
                'next_storage_id' => 0,
                'next_storage_name' => '',
                'next_storage_address' => '',
                'curr_storage_manage_id' => $storageManageInfo['id'],
                'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                'materiel_type_id' => $storageManageInfo['type_id'],
                'materiel_name' => $storageManageInfo['materiel_name'],
                'type_name' => $storageManageInfo['type_name'],
                'materiel_no' => $storageManageInfo['materiel_no'],
                'operate_num' => $data['num'],
                'last_storage_num' => $storageManageInfo['in_storage_num'],
                'next_storage_num' => $storageManageInfo['in_storage_num'] - $data['num'],
                'sell_price' => $storageManageInfo['materiel_mean_cost'],
                'materiel_mean_cost' => $storageManageInfo['materiel_mean_cost'],
                'remark' => empty($data['remark'])?'':$data['remark'],
                'main_id' => $data['main_id'],
                'user_id' => $data['user_id'],
                'out_storage_time' => time(),
                'created_at' => time(),
                'label_name'=>!empty($data['label_name'])?$data['label_name']:'',
            ]);

            if($storageManageInfo['virtual_storage_num'] > 0) {
                StorageManageModel::where('id', $data['id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num - '.$data['num']),
                        'virtual_storage_num' => DB::raw('virtual_storage_num - '.$data['num'])
                    ]);
            }
            else {
                StorageManageModel::where('id', $data['id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num - '.$data['num']),
                    ]);
            }

            MessageService::sendAlertSms(
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['in_storage_num'] - $data['num'],
                $storageManageInfo['alert_num'],
                $data,
                $storageManageInfo['storage_id'],
                $storageManageInfo['storage_name'],
                $data['num']
            );

            MessageService::sendShortSms(
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['in_storage_num'] - $data['num'],
                $data,
                $storageManageInfo['storage_name'],
                $storageManageInfo['storage_id']
            );

            MessageService::sendOutSms(
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['in_storage_num'],
                $storageManageInfo['storage_name'],
                $data['num'],
                $data,
                $storageManageInfo['storage_id'],
                $storageManageInfo['alert_num'],
            );

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('出库1'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '出库失败！', 'data' => ''];
        }
    }

    static public function setAlertNum($data)
    {
        StorageManageModel::where('id', $data['id'])->update(['alert_num' => $data['alert_num']]);

        return ['code' => 0, 'msg' => 'success', 'data' => ''];
    }

    public static function exportData(array $user, $data)
    {
        $condition = [];

        $keyword = empty($data['keyword'])?'':$data['keyword'];

//        if(!empty($data['f_class_id'])) {
//            $condition['c.id'] = ['EQ' => $data['f_class_id']];
//        }

        if(!empty($data['s_class_id'])) {
            $condition['a.materiel_class_id'] = ['EQ' => $data['s_class_id']];
        }

        if(!empty($data['storage_id'])) {
            $condition['a.storage_id'] = ['EQ' => $data['storage_id']];
        }

        $query = StorageManageModel::select(
            'a.id',
            'd.materiel_name',
            'a.type_id',
            'd.type_name',
            'd.materiel_no',
            'a.materiel_mean_cost',
            'a.storage_id',
            'e.storage_name',
            'e.storage_address',
            'a.in_storage_num',
            'a.alert_num',
            'c.id as f_class_id',
            'c.class_name as f_class_name',
            'c.class_no as f_class_no',
            'b.id as s_class_id',
            'b.class_name as s_class_name',
            'b.class_no as s_class_no',
            'd.materiel_img',
            'd.remark',
            'd.is_use_serial'
        )
            ->from('storage_manage as a')
            ->leftJoin('materiel_class as b', 'a.materiel_class_id', '=', 'b.id')
            ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id')
            ->leftJoin('materiel_type as d', 'd.id', '=', 'a.type_id')
            ->leftJoin('storage as e', 'e.id', '=', 'a.storage_id')
            ->where($condition)
            ->where('a.delete_flag', 0)
            ->where($user)
            ->where(function($query) use ($keyword) {
                $query->orWhere('d.materiel_name', 'like', '%'.$keyword.'%')
                    ->orWhere('d.type_name', 'like', '%'.$keyword.'%')
                    ->orWhere('d.materiel_no', 'like', '%'.$keyword.'%')
                    ->orWhere('b.class_no', 'like', '%'.$keyword.'%');
            });

//        if(!empty($data['class_no'])) {
//            $keyword = empty($data['class_no'])?'':$data['class_no'];
//
//            $query->where(function($query) use ($keyword) {
//                $query->orWhere('b.class_no', 'like', '%'.$keyword.'%');
//                $query->orWhere('c.class_no', 'like', '%'.$keyword.'%');
//            });
//        }
//
//        if(!empty($data['max_mean_cost']) && !empty($data['min_mean_cost'])) {
//            $query->whereBetween('a.materiel_mean_cost', [$data['min_mean_cost'], $data['max_mean_cost']]);
//        }
//        else if(!empty($data['max_mean_cost']) && empty($data['min_mean_cost'])) {
//            $query->where('a.materiel_mean_cost', '<=', $data['max_mean_cost']);
//        }
//        else if(empty($data['max_mean_cost']) && !empty($data['min_mean_cost'])) {
//            $query->where('a.materiel_mean_cost', '>=', $data['min_mean_cost']);
//        }
//        //
//        if(!empty($data['max_storage_num']) && !empty($data['min_storage_num'])) {
//            $query->whereBetween('a.in_storage_num', [$data['min_storage_num'], $data['max_storage_num']]);
//        }
//        else if(!empty($data['max_storage_num']) && empty($data['min_storage_num'])) {
//            $query->where('a.in_storage_num', '<=', $data['max_storage_num']);
//        }
//        else if(empty($data['max_storage_num']) && !empty($data['min_storage_num'])) {
//            $query->where('a.in_storage_num', '>=', $data['min_storage_num']);
//        }

        return $query->orderBy('a.materiel_no')
            ->get()->toArray();
    }

    private static function clearLog($data)
    {
        LogInStorageModel::where('main_id', $data['main_id'])
            ->update(['delete_flag' => 1]);

        LogOutStorageModel::where('main_id', $data['main_id'])
            ->update(['delete_flag' => 1]);

        LogPackageModel::where('main_id', $data['main_id'])
            ->update(['delete_flag' => 1]);

        return true;
    }

    public static function detail(array $data)
    {
        $result = StorageManageModel::detail($data);

        if($result['is_product_materiel']) {
            $result['product_content'] = MaterielProductContentModel::select(
                'a.type_id',
                'a.num',
                'b.materiel_name',
                'b.materiel_no',
                'b.materiel_img',
                'b.type_name',
                'b.is_use_serial'
            )
                ->from('materiel_product_content as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
                ->where('product_id', $result['type_id'])
                ->get()->toArray();
        }
        else {
            $result['product_content'] = [];
        }

        return $result;
    }

    public static function usedSerialList(array $data)
    {
        $typeId = array_filter(explode(',', $data['type_id']), function($v) { return $v !== ''; });

        $serialInfo = SerialNumberModel::select(
            'id',
            'serial_no',
            'goods_id as type_id',
            'storage_manage_id'
        )
            ->where('status', 0)
            ->whereIn('goods_id', $typeId)
            ->get()->toArray();

        $result = [];
        foreach($serialInfo as $key => $value) {
            $materialInfo = MaterielTypeModel::where('id', $value['type_id'])->first();
            $result[$value['type_id']]['type_id'] = $value['type_id'];
            $result[$value['type_id']]['materiel_name'] = $materialInfo['materiel_name'];
            $result[$value['type_id']]['type_name'] = $materialInfo['type_name'];
            $result[$value['type_id']]['serial_info'][] = $value;
        }

        return array_values($result);
    }

    /**
     * 处理套件返仓数据
     * @param type_id    商品id
     * @param storage_id 仓库id
     * @param num        返仓数量
     * @param remark     备注
     * @param serial_info 序列号信息（开启了序列号，传相应数据）
     * @param serial_id   序列号id
     * @param storage_manage_id 库存id
     * @param num               序列号数量
     */
    public static function handleReturnPackageStore($data){
        $smId = 0;
        $smCondition = [];
        $logData = [];
        //查询套餐库存信息
        $productStorageManageInfo = StorageManageModel::where([
            'id'=>$data['storage_manage_id'],
            'type_id'=>$data['product_id'],
            'is_product_materiel'=>1,
            'delete_flag'=>0
            ])->first();

        if(empty($productStorageManageInfo))
        return ['code'=>1,'msg'=>'没有找到，套餐'.$productStorageManageInfo['materiel_name'].'库存信息！','data'=>''];

        if($productStorageManageInfo['in_storage_num']-$data['product_num'] < 0){
            return ['code'=>1,'msg'=>'套餐'.$productStorageManageInfo['materiel_name'].'库存数量不足！','data'=>''];
        }

        if($productStorageManageInfo['virtual_storage_num']-$data['product_num'] < 0){
            return ['code'=>1,'msg'=>'套餐'.$productStorageManageInfo['materiel_name'].'虚拟库存数量不足！','data'=>''];

        }
        $productContent = json_decode($data['product_content'],true);

        if(!empty($productContent)){
        DB::beginTransaction();
        try {
            foreach ($productContent as $key=>$val){
                //查询组件中的商品信息
                $productInfo = MaterielProductContentModel::select('a.num','b.*')
                        ->from("materiel_product_content as a")
                        ->leftJoin('materiel_type as b','a.type_id','=','b.id')
                        ->where('a.product_id',$data['product_id'])
                        ->where('b.id',$val['type_id'])
                        ->where('a.delete_flag',0)
                        ->where('b.delete_flag',0)
                        ->first();
                        if(empty($productInfo))
                        return ['code'=>1,'msg'=>'没有找到，商品'.$productInfo['materiel_name'].'的信息','data'=>''];

                       /* DB::enableQueryLog(); */
                        //查询默认仓库和货架信息
                        if(empty($val['shelf_id']) || empty($val['location_id'])){

                            $storageInfo = StorageModel::select('a.*','b.id as shelf_id','c.id as location_id')->from('storage as a')
                            ->leftJoin('storage_shelf as b','b.storage_id','=','a.id')
                            ->leftJoin('storage_shelf_location as c','c.shelf_id','=','b.id')
                            ->where('a.id',$val['storage_id'])
                            ->where('a.delete_flag',0)
                            ->where('b.status',1)
                            ->where('c.location_type',1)
                            ->where('b.shelf_type',1)
                            ->first();

                        }else{
                            $storageInfo = StorageModel::select('a.*','b.id as shelf_id','c.id as location_id')->from('storage as a')
                            ->leftJoin('storage_shelf as b','b.storage_id','=','a.id')
                            ->leftJoin('storage_shelf_location as c','c.shelf_id','=','b.id')
                            ->where('a.id',$val['storage_id'])
                            ->where('b.id',$val['shelf_id'])
                            ->where('c.id',$val['location_id'])
                            ->where('a.delete_flag',0)
                            ->where('b.status',1)
                            ->first();

                        }
                        /* echo "<pre>";
                       var_dump($storageInfo);die; */
                       if(empty($storageInfo))
                       return ['code'=>1,'msg'=>'没有找到，商品'.$productInfo['materiel_name'].'选择的仓库信息','data'=>''];
                        $mcInfo = MaterielClassModel::select('id','class_name','class_no')
                        ->where(['delete_flag'=>0,'id'=>$productInfo['materiel_class_id']])->first();

                //查询库存信息的条件
                $smCondition=[
                    'type_id'     => $val['type_id'],
                    'storage_id'  => $val['storage_id'],
                    'delete_flag' => 0
                ];
                //DB::enableQueryLog();
                //查询库存信息
                $smInfo = StorageManageModel::where($smCondition)->first();
               /*  echo "<pre>";
                echo var_dump(DB::getQueryLog());die; */
               //判断商品仓库对应的库存是否存在，存在就修改在库数量和虚拟数量，不存在就新增库存信息
                if(!empty($smInfo)){//有商品库存信息
                    StorageManageModel::where('id',$smInfo['id'])->update([
                        'in_storage_num' => $smInfo['in_storage_num'] + $val['num'],
                        'virtual_storage_num' => $smInfo['virtual_storage_num'] + $val['num']
                    ]);

                }else{//没有商品库存信息

                    $smId = StorageManageModel::insertGetId([
                        'materiel_class_id'=>!empty($mcInfo['id'])?$mcInfo['id']:0,
                        'materiel_class_name'=>!empty($mcInfo['materiel_class_name'])?$mcInfo['materiel_class_name']:"",
                        'materiel_class_no'=>!empty($mcInfo['materiel_class_no'])?$mcInfo['materiel_class_no']:"",
                        'type_id'=>$val['type_id'],
                        'materiel_name'=>!empty($productInfo['materiel_name'])?$productInfo['materiel_name']:"",
                        'type_name'=>!empty($productInfo['type_name'])?$productInfo['type_name']:"",
                        'materiel_no'=>!empty($productInfo['materiel_no'])?$productInfo['materiel_no']:"",
                        'materiel_mean_cost'=>!empty($productInfo['cost'])?$productInfo['cost']:"",
                        'storage_id'=>$storageInfo['id'],
                        'storage_name'=>!empty($storageInfo['storage_name'])?$storageInfo['storage_name']:"",
                        'storage_address'=>!empty($storageInfo['storage_address'])?$storageInfo['storage_address']:"",
                        'in_storage_num'=>$val['num'],
                        'virtual_storage_num'=>$val['num'],
                        'main_id'=>$data['main_id'],
                        'in_storage_time'=>strtotime($data['in_storage_time']),
                        'shelf_id'=>!empty($storageInfo['shelf_id'])?$storageInfo['shelf_id']:0,
                        'location_id'=>!empty($storageInfo['location_id'])?$storageInfo['location_id']:0,
                        'created_at'=>time(),
                    ]);

                }
                $serialNumberList="";
                //开启序列号商品相关操作
                if($productInfo['is_use_serial'] == 1){//开启序列号
                    if(!empty($val['serial_info'])){
                         $serialNum = 0;
                         /* echo "<pre>";
                         var_dump($val['serial_info']);die; */
                         foreach ($val['serial_info'] as $sKey=>$sVal){
                           $snInfo = SerialNumberModel::where(['id'=>$sVal['serial_id'],'status'=>1])->first();

                           if(!empty($snInfo)){

                              $serialNumberList .= $snInfo['serial_no'].',';

                           }else{
                               $i=$sKey+1;
                              return ['code'=>1,'msg'=>'第'.$i.'个序列号状态不正确或不存在!','data'=>''];
                           }

                            if(!empty($smInfo)){
                                if($smInfo['id'] == $sVal['storage_manage_id']){//序列号所在库存与传来的仓库id查询的库存一致
                                    SerialNumberModel::where(['id'=>$sVal['serial_id'],'status'=>1])
                                    ->update([
                                        'package_id'=>0,
                                        'package_storage_id'=>0,
                                    ]);
                                }else{//序列号库存与传来的仓库id查询的库存不一致,把原有的序列号库存id改成传来的
                                    SerialNumberModel::where(['id'=>$sVal['serial_id'],'status'=>1])
                                        ->update([
                                            'package_id'=>0,
                                            'package_storage_id'=>0,
                                            'storage_manage_id'=>$smInfo['id'],
                                        ]);
                                }
                            }else{
                                SerialNumberModel::where(['id'=>$sVal['serial_id'],'status'=>1])
                                ->update([
                                    'package_id'=>0,
                                    'package_storage_id'=>0,
                                    'storage_manage_id'=>$smId,
                                ]);
                            }

                            $serialNum += $sVal['num'];
                         }

                         if($val['num'] != $serialNum){
                            return ['code'=>1,'msg'=>'商品'.$productInfo['materiel_name'].'返仓数量与选择的序列号数量不相等','data'=>''];
                         }

                     }else{
                        return ['code'=>1,'msg'=>'商品'.$productInfo['materiel_name'].'开启了序列号，请选择序列号！','data'=>''];
                     }
                }else{//未开启序列号的商品

                    if($productInfo['num']*$data['product_num'] != $val['num']){
                        return ['code'=>1,'msg'=>'商品'.$productInfo['materiel_name'].'返仓数量不正确，数量应是：'.$productInfo['num']*$data['product_num'],'data'=>''];
                    }
              }

              if(!empty($serialNumberList))
              $serialNumberList = substr($serialNumberList,0,strrpos($serialNumberList,","));

              $logData[] = [
                  'type' => 0,
                  'curr_storage_manage_id' => !empty($smInfo)?$smInfo['id']:$smId,
                  'storage_id' => $storageInfo['id'],
                  'storage_name' => $storageInfo['storage_name'],
                  'storage_address' => $storageInfo['storage_address'],
                  'materiel_class_id' => $productInfo['materiel_class_id'],
                  'materiel_class_name' => !empty($mcInfo['class_name'])?$mcInfo['class_name']:"",
                  'materiel_class_no' => !empty($mcInfo['class_no'])?$mcInfo['class_no']:"",
                  'materiel_type_id' => $val['type_id'],
                  'materiel_name' => $productInfo['materiel_name'],
                  'type_name' => $productInfo['type_name'],
                  'materiel_no' => $productInfo['materiel_no'],
                  /* 'purchase_no' => $productInfo['product_no'], */
                  'operate_num' => $productInfo['num'],
                  'last_storage_num' => !empty($smInfo)?$smInfo['in_storage_num']:0,
                  'next_storage_num' => !empty($smInfo)?$smInfo['in_storage_num']+$val['num']:$val['num'],
                  'materiel_mean_cost' => $productInfo['cost'],
                  'serial_number' => !empty($serialNumberList)?$serialNumberList:"",
                  'all_id_type' => 6,
                  'all_id' => $data['product_id'],
                  'user_id' => $data['user_id'],
                  'main_id' => $data['main_id'],
                  'in_storage_time' => strtotime($data['in_storage_time']),
                  'created_at' => time(),
                  'shelf_id' => !empty($storageInfo['shelf_id'])?$storageInfo['shelf_id']:'',
                  'remark' => empty($val['remark'])?'':$val['remark'],
                  'location_id' => !empty($storageInfo['location_id'])?$storageInfo['location_id']:'',
              ];
           }
           if(!empty($logData)) {
               LogInStorageModel::insert($logData);
           }

           StorageManageModel::where('id',$productStorageManageInfo['id'])->update([
               'in_storage_num' => $productStorageManageInfo['in_storage_num'] - $data['product_num'],
               'virtual_storage_num' => $productStorageManageInfo['virtual_storage_num'] - $data['product_num']
           ]);
           PackageComponentWarehouseLogModel::insertGetId([
               'storage_manage_id' => $productStorageManageInfo['id'],
               'product_id'        => $productStorageManageInfo['type_id'],
               'operation_num'     => $data['product_num'],
               'next_storage_num'  => $productStorageManageInfo['in_storage_num']-$data['product_num'],
               'main_id'           => $productStorageManageInfo['main_id'],
               'operation_time'    => strtotime($data['in_storage_time']),
               'created_at'        => time()
           ]);

           DB::commit();
           return ['code'=>0,'msg'=>'success','data'=>''];
       } catch (Exception $e) {
           DB::rollBack();
           Log::debug('组件返仓异常'.var_export($e->getMessage(), true));
           return ['code'=>1,'msg'=>'组件返仓失败！','data'=>''];
       }
    }else{
        return ['code'=>1,'msg'=>'组件里的商品，不能为空！','data'=>''];
    }
  }
    public static function serialList(array $data)
    {
        $materielTypeInfo = MaterielTypeModel::where([
            'id' => $data['type_id']
        ])
            ->first();

        if(!$materielTypeInfo['is_product_materiel']) {
            $data['pageSize'] = $data['pageSize'] ?? 20;
            $data['currentPage'] = $data['currentPage'] ?? 1;

            $result = SerialNumberModel::select(
                'a.id',
                'serial_no',
                'goods_id as materiel_type_id',
                'b.materiel_name',
                'b.type_name',
                'b.materiel_no',
                'b.materiel_img',
                'c.in_storage_num',
                'd.id as storage_id',
                'd.storage_name',
                'd.storage_address',
                'b.is_product_materiel'
            )
                ->from('serial_number as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.goods_id')
                ->leftJoin('storage_manage as c', 'c.id', '=', 'a.storage_manage_id')
                ->leftJoin('storage as d', 'd.id', '=', 'c.storage_id')
                ->where([
                    'goods_id' => $data['type_id'],
                    'storage_manage_id' => $data['id'],
                    'status' => 1,
                    'package_storage_id' => 0
                ])
                ->paginate($data['pageSize'],['*'], '',$data['currentPage']);
        }
        else {
            $result = StorageManageModel::select(
                'a.id',
                'a.in_storage_num',
                'b.id as materiel_type_id',
                'b.materiel_name',
                'b.type_name',
                'b.materiel_no',
                'b.materiel_img',
                'c.id as storage_id',
                'c.storage_name',
                'b.is_product_materiel'
            )
                ->from('storage_manage as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
                ->leftJoin('storage as c', 'c.id', '=', 'a.storage_id')
                ->where('a.id', $data['id'])
                ->first();

            $productContent = MaterielProductContentModel::select(
                'a.id',
                'a.num',
                'a.type_id',
                'a.product_id',
                'b.materiel_name',
                'b.type_name',
                'b.materiel_no',
                'b.materiel_img',
                'b.is_use_serial'
            )
                ->from('materiel_product_content as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
                ->where('product_id', $data['type_id'])
                ->get()->toArray();

            foreach($productContent as &$value) {
                $serialNumberData = SerialNumberModel::select(
                    'id as serial_id',
                    'package_storage_id as storage_manage_id',
                    'serial_no'
                )
                    ->from('serial_number as a')
                    ->where('package_id', $data['type_id'])
                    ->where('package_storage_id', $data['id'])
                    ->where('goods_id', $value['type_id'])
                    ->where('status', 1)
                    ->get()->toArray();

                if(empty($serialNumberData)) {
                    $value['product_serial_list'] = [];
                }
                else {
                    $value['product_serial_list'] = $serialNumberData;
                }
            }

            $result['product_content'] = $productContent;
        }

        return $result;
    }
}
